{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "Logica_example_Avengers_and_PostgreSQL.ipynb",
      "provenance": [],
      "collapsed_sections": [],
      "authorship_tag": "ABX9TyPrD/4G4NwaciqD33rgTwsS",
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/EvgSkv/logica/blob/main/examples/Logica_example_Avengers_and_PostgreSQL.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "S26GH8bkUrmK"
      },
      "source": [
        "# Logica example: Avengers and PostgreSQL\n",
        "\n",
        "At the moment only BigQuery is fully supported in Logica, but in the future we plan to support other engines.\n",
        "There is already an **experimental** support for PostgreSQL.\n",
        "\n",
        "Engine is controlled with `@Engine` annotation.\n",
        "\n",
        "In this CoLab we give an example of how mortality of Avengers can be computed\n",
        "with Logica on PostgreSQL engine.\n",
        "\n",
        "The Avengers dataset published by [FiveThirtyEight](https://fivethirtyeight.com/) is used."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ltqvl1qmVkfR"
      },
      "source": [
        "## Install Logica and PostgreSQL."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "W7NuEqRJPMzt",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "fc90c33b-cd59-4fc8-eae7-57cc963d9723"
      },
      "source": [
        "# Install Logica.\n",
        "!pip install logica\n",
        "\n",
        "# Install postgresql server.\n",
        "!sudo apt-get -y -qq update\n",
        "!sudo apt-get -y -qq install postgresql\n",
        "!sudo service postgresql start\n",
        "\n",
        "# Prepare database for Logica.\n",
        "!sudo -u postgres psql -c \"CREATE USER logica WITH SUPERUSER\"\n",
        "!sudo -u postgres psql -c \"ALTER USER logica PASSWORD 'logica';\"\n",
        "!sudo -u postgres psql -U postgres -c 'CREATE DATABASE logica;'\n",
        "\n",
        "# Connect to the database.\n",
        "from logica import colab_logica\n",
        "from sqlalchemy import create_engine\n",
        "import pandas\n",
        "engine = create_engine('postgresql+psycopg2://logica:logica@127.0.0.1', pool_recycle=3600);\n",
        "connection = engine.connect();\n",
        "colab_logica.SetDbConnection(connection)"
      ],
      "execution_count": 1,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Collecting logica\n",
            "\u001b[?25l  Downloading https://files.pythonhosted.org/packages/d7/1d/5ffb3e1a4531edaaeba961f1c0c398ed113d7640908bd1504f057d1491c6/logica-1.3.14-py3-none-any.whl (69kB)\n",
            "\r\u001b[K     |████▊                           | 10kB 16.5MB/s eta 0:00:01\r\u001b[K     |█████████▍                      | 20kB 20.6MB/s eta 0:00:01\r\u001b[K     |██████████████                  | 30kB 24.6MB/s eta 0:00:01\r\u001b[K     |██████████████████▉             | 40kB 26.3MB/s eta 0:00:01\r\u001b[K     |███████████████████████▌        | 51kB 28.8MB/s eta 0:00:01\r\u001b[K     |████████████████████████████▏   | 61kB 28.1MB/s eta 0:00:01\r\u001b[K     |████████████████████████████████| 71kB 7.1MB/s \n",
            "\u001b[?25hInstalling collected packages: logica\n",
            "Successfully installed logica-1.3.14\n",
            "debconf: unable to initialize frontend: Dialog\n",
            "debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 76, <> line 12.)\n",
            "debconf: falling back to frontend: Readline\n",
            "debconf: unable to initialize frontend: Readline\n",
            "debconf: (This frontend requires a controlling tty.)\n",
            "debconf: falling back to frontend: Teletype\n",
            "dpkg-preconfigure: unable to re-open stdin: \n",
            "Selecting previously unselected package cron.\n",
            "(Reading database ... 160706 files and directories currently installed.)\n",
            "Preparing to unpack .../00-cron_3.0pl1-128.1ubuntu1_amd64.deb ...\n",
            "Unpacking cron (3.0pl1-128.1ubuntu1) ...\n",
            "Selecting previously unselected package logrotate.\n",
            "Preparing to unpack .../01-logrotate_3.11.0-0.1ubuntu1_amd64.deb ...\n",
            "Unpacking logrotate (3.11.0-0.1ubuntu1) ...\n",
            "Selecting previously unselected package netbase.\n",
            "Preparing to unpack .../02-netbase_5.4_all.deb ...\n",
            "Unpacking netbase (5.4) ...\n",
            "Preparing to unpack .../03-libpq-dev_10.17-0ubuntu0.18.04.1_amd64.deb ...\n",
            "Unpacking libpq-dev (10.17-0ubuntu0.18.04.1) over (10.16-0ubuntu0.18.04.1) ...\n",
            "Preparing to unpack .../04-libpq5_10.17-0ubuntu0.18.04.1_amd64.deb ...\n",
            "Unpacking libpq5:amd64 (10.17-0ubuntu0.18.04.1) over (10.16-0ubuntu0.18.04.1) ...\n",
            "Selecting previously unselected package postgresql-client-common.\n",
            "Preparing to unpack .../05-postgresql-client-common_190ubuntu0.1_all.deb ...\n",
            "Unpacking postgresql-client-common (190ubuntu0.1) ...\n",
            "Selecting previously unselected package postgresql-client-10.\n",
            "Preparing to unpack .../06-postgresql-client-10_10.17-0ubuntu0.18.04.1_amd64.deb ...\n",
            "Unpacking postgresql-client-10 (10.17-0ubuntu0.18.04.1) ...\n",
            "Selecting previously unselected package ssl-cert.\n",
            "Preparing to unpack .../07-ssl-cert_1.0.39_all.deb ...\n",
            "Unpacking ssl-cert (1.0.39) ...\n",
            "Selecting previously unselected package postgresql-common.\n",
            "Preparing to unpack .../08-postgresql-common_190ubuntu0.1_all.deb ...\n",
            "Adding 'diversion of /usr/bin/pg_config to /usr/bin/pg_config.libpq-dev by postgresql-common'\n",
            "Unpacking postgresql-common (190ubuntu0.1) ...\n",
            "Selecting previously unselected package postgresql-10.\n",
            "Preparing to unpack .../09-postgresql-10_10.17-0ubuntu0.18.04.1_amd64.deb ...\n",
            "Unpacking postgresql-10 (10.17-0ubuntu0.18.04.1) ...\n",
            "Selecting previously unselected package postgresql.\n",
            "Preparing to unpack .../10-postgresql_10+190ubuntu0.1_all.deb ...\n",
            "Unpacking postgresql (10+190ubuntu0.1) ...\n",
            "Selecting previously unselected package sysstat.\n",
            "Preparing to unpack .../11-sysstat_11.6.1-1ubuntu0.1_amd64.deb ...\n",
            "Unpacking sysstat (11.6.1-1ubuntu0.1) ...\n",
            "Setting up sysstat (11.6.1-1ubuntu0.1) ...\n",
            "debconf: unable to initialize frontend: Dialog\n",
            "debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 76.)\n",
            "debconf: falling back to frontend: Readline\n",
            "\n",
            "Creating config file /etc/default/sysstat with new version\n",
            "update-alternatives: using /usr/bin/sar.sysstat to provide /usr/bin/sar (sar) in auto mode\n",
            "Created symlink /etc/systemd/system/multi-user.target.wants/sysstat.service → /lib/systemd/system/sysstat.service.\n",
            "Setting up ssl-cert (1.0.39) ...\n",
            "debconf: unable to initialize frontend: Dialog\n",
            "debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 76.)\n",
            "debconf: falling back to frontend: Readline\n",
            "Setting up libpq5:amd64 (10.17-0ubuntu0.18.04.1) ...\n",
            "Setting up cron (3.0pl1-128.1ubuntu1) ...\n",
            "Adding group `crontab' (GID 110) ...\n",
            "Done.\n",
            "Created symlink /etc/systemd/system/multi-user.target.wants/cron.service → /lib/systemd/system/cron.service.\n",
            "update-rc.d: warning: start and stop actions are no longer supported; falling back to defaults\n",
            "invoke-rc.d: could not determine current runlevel\n",
            "invoke-rc.d: policy-rc.d denied execution of start.\n",
            "Setting up logrotate (3.11.0-0.1ubuntu1) ...\n",
            "Setting up netbase (5.4) ...\n",
            "Setting up libpq-dev (10.17-0ubuntu0.18.04.1) ...\n",
            "Setting up postgresql-client-common (190ubuntu0.1) ...\n",
            "Setting up postgresql-common (190ubuntu0.1) ...\n",
            "debconf: unable to initialize frontend: Dialog\n",
            "debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 76.)\n",
            "debconf: falling back to frontend: Readline\n",
            "Adding user postgres to group ssl-cert\n",
            "\n",
            "Creating config file /etc/postgresql-common/createcluster.conf with new version\n",
            "Building PostgreSQL dictionaries from installed myspell/hunspell packages...\n",
            "Removing obsolete dictionary files:\n",
            "Created symlink /etc/systemd/system/multi-user.target.wants/postgresql.service → /lib/systemd/system/postgresql.service.\n",
            "invoke-rc.d: could not determine current runlevel\n",
            "invoke-rc.d: policy-rc.d denied execution of start.\n",
            "Setting up postgresql-client-10 (10.17-0ubuntu0.18.04.1) ...\n",
            "update-alternatives: using /usr/share/postgresql/10/man/man1/psql.1.gz to provide /usr/share/man/man1/psql.1.gz (psql.1.gz) in auto mode\n",
            "Setting up postgresql-10 (10.17-0ubuntu0.18.04.1) ...\n",
            "debconf: unable to initialize frontend: Dialog\n",
            "debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 76.)\n",
            "debconf: falling back to frontend: Readline\n",
            "Creating new PostgreSQL cluster 10/main ...\n",
            "/usr/lib/postgresql/10/bin/initdb -D /var/lib/postgresql/10/main --auth-local peer --auth-host md5\n",
            "The files belonging to this database system will be owned by user \"postgres\".\n",
            "This user must also own the server process.\n",
            "\n",
            "The database cluster will be initialized with locale \"en_US.UTF-8\".\n",
            "The default database encoding has accordingly been set to \"UTF8\".\n",
            "The default text search configuration will be set to \"english\".\n",
            "\n",
            "Data page checksums are disabled.\n",
            "\n",
            "fixing permissions on existing directory /var/lib/postgresql/10/main ... ok\n",
            "creating subdirectories ... ok\n",
            "selecting default max_connections ... 100\n",
            "selecting default shared_buffers ... 128MB\n",
            "selecting default timezone ... Etc/UTC\n",
            "selecting dynamic shared memory implementation ... posix\n",
            "creating configuration files ... ok\n",
            "running bootstrap script ... ok\n",
            "performing post-bootstrap initialization ... ok\n",
            "syncing data to disk ... ok\n",
            "\n",
            "Success. You can now start the database server using:\n",
            "\n",
            "    /usr/lib/postgresql/10/bin/pg_ctl -D /var/lib/postgresql/10/main -l logfile start\n",
            "\n",
            "Ver Cluster Port Status Owner    Data directory              Log file\n",
            "\u001b[31m10  main    5432 down   postgres /var/lib/postgresql/10/main /var/log/postgresql/postgresql-10-main.log\u001b[0m\n",
            "update-alternatives: using /usr/share/postgresql/10/man/man1/postmaster.1.gz to provide /usr/share/man/man1/postmaster.1.gz (postmaster.1.gz) in auto mode\n",
            "invoke-rc.d: could not determine current runlevel\n",
            "invoke-rc.d: policy-rc.d denied execution of start.\n",
            "Setting up postgresql (10+190ubuntu0.1) ...\n",
            "Processing triggers for man-db (2.8.3-2ubuntu0.1) ...\n",
            "Processing triggers for libc-bin (2.27-3ubuntu1.2) ...\n",
            "/sbin/ldconfig.real: /usr/local/lib/python3.7/dist-packages/ideep4py/lib/libmkldnn.so.0 is not a symbolic link\n",
            "\n",
            "Processing triggers for systemd (237-3ubuntu10.47) ...\n",
            " * Starting PostgreSQL 10 database server\n",
            "   ...done.\n",
            "CREATE ROLE\n",
            "ALTER ROLE\n",
            "CREATE DATABASE\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.7/dist-packages/psycopg2/__init__.py:144: UserWarning: The psycopg2 wheel package will be renamed from release 2.8; in order to keep installing from binary please use \"pip install psycopg2-binary\" instead. For details see: <http://initd.org/psycopg/docs/install.html#binary-install-from-pypi>.\n",
            "  \"\"\")\n"
          ],
          "name": "stderr"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Yt6mtsC8Vnww"
      },
      "source": [
        "## Load dataset"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "J4zesAMzNQXv"
      },
      "source": [
        "import urllib.request\n",
        "import pandas\n",
        "import io\n",
        "\n",
        "url = urllib.request.urlopen('https://github.com/fivethirtyeight/data/blob/master/avengers/avengers.csv?raw=True')\n",
        "text = url.read().decode('utf-8', errors='ignore').lower()\n",
        "f = io.StringIO(text)\n",
        "avengers_data = pandas.read_csv(f)\n",
        "avengers_data.to_sql('avengers', engine, if_exists='replace', method='multi')\n"
      ],
      "execution_count": 2,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "VcA_QMUAVpjJ"
      },
      "source": [
        "## Calculate mortality"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "NkehJ8LhPdFI",
        "colab": {
          "resources": {
            "http://localhost:8080/nbextensions/google.colab/tabbar.css": {
              "data": "Lmdvb2ctdGFie3Bvc2l0aW9uOnJlbGF0aXZlO3BhZGRpbmc6NHB4IDhweDtjb2xvcjojMDBjO3RleHQtZGVjb3JhdGlvbjp1bmRlcmxpbmU7Y3Vyc29yOmRlZmF1bHR9Lmdvb2ctdGFiLWJhci10b3AgLmdvb2ctdGFie21hcmdpbjoxcHggNHB4IDAgMDtib3JkZXItYm90dG9tOjA7ZmxvYXQ6bGVmdH0uZ29vZy10YWItYmFyLXRvcDphZnRlciwuZ29vZy10YWItYmFyLWJvdHRvbTphZnRlcntjb250ZW50OiIgIjtkaXNwbGF5OmJsb2NrO2hlaWdodDowO2NsZWFyOmJvdGg7dmlzaWJpbGl0eTpoaWRkZW59Lmdvb2ctdGFiLWJhci1ib3R0b20gLmdvb2ctdGFie21hcmdpbjowIDRweCAxcHggMDtib3JkZXItdG9wOjA7ZmxvYXQ6bGVmdH0uZ29vZy10YWItYmFyLXN0YXJ0IC5nb29nLXRhYnttYXJnaW46MCAwIDRweCAxcHg7Ym9yZGVyLXJpZ2h0OjB9Lmdvb2ctdGFiLWJhci1lbmQgLmdvb2ctdGFie21hcmdpbjowIDFweCA0cHggMDtib3JkZXItbGVmdDowfS5nb29nLXRhYi1ob3ZlcntiYWNrZ3JvdW5kOiNlZWV9Lmdvb2ctdGFiLWRpc2FibGVke2NvbG9yOiM2NjZ9Lmdvb2ctdGFiLXNlbGVjdGVke2NvbG9yOiMwMDA7YmFja2dyb3VuZDojZmZmO3RleHQtZGVjb3JhdGlvbjpub25lO2ZvbnQtd2VpZ2h0OmJvbGQ7Ym9yZGVyOjFweCBzb2xpZCAjNmI5MGRhfS5nb29nLXRhYi1iYXItdG9we3BhZGRpbmctdG9wOjVweCFpbXBvcnRhbnQ7cGFkZGluZy1sZWZ0OjVweCFpbXBvcnRhbnQ7Ym9yZGVyLWJvdHRvbToxcHggc29saWQgIzZiOTBkYSFpbXBvcnRhbnR9Lmdvb2ctdGFiLWJhci10b3AgLmdvb2ctdGFiLXNlbGVjdGVke3RvcDoxcHg7bWFyZ2luLXRvcDowO3BhZGRpbmctYm90dG9tOjVweH0uZ29vZy10YWItYmFyLWJvdHRvbSAuZ29vZy10YWItc2VsZWN0ZWR7dG9wOi0xcHg7bWFyZ2luLWJvdHRvbTowO3BhZGRpbmctdG9wOjVweH0uZ29vZy10YWItYmFyLXN0YXJ0IC5nb29nLXRhYi1zZWxlY3RlZHtsZWZ0OjFweDttYXJnaW4tbGVmdDowO3BhZGRpbmctcmlnaHQ6OXB4fS5nb29nLXRhYi1iYXItZW5kIC5nb29nLXRhYi1zZWxlY3RlZHtsZWZ0Oi0xcHg7bWFyZ2luLXJpZ2h0OjA7cGFkZGluZy1sZWZ0OjlweH0uZ29vZy10YWItYmFye21hcmdpbjowO2JvcmRlcjowO3BhZGRpbmc6MDtsaXN0LXN0eWxlOm5vbmU7Y3Vyc29yOmRlZmF1bHQ7b3V0bGluZTpub25lO2JhY2tncm91bmQ6I2ViZWZmOX0uZ29vZy10YWItYmFyLWNsZWFye2NsZWFyOmJvdGg7aGVpZ2h0OjA7b3ZlcmZsb3c6aGlkZGVufS5nb29nLXRhYi1iYXItc3RhcnR7ZmxvYXQ6bGVmdH0uZ29vZy10YWItYmFyLWVuZHtmbG9hdDpyaWdodH0qIGh0bWwgLmdvb2ctdGFiLWJhci1zdGFydHttYXJnaW4tcmlnaHQ6LTNweH0qIGh0bWwgLmdvb2ctdGFiLWJhci1lbmR7bWFyZ2luLWxlZnQ6LTNweH0=",
              "ok": true,
              "headers": [
                [
                  "content-type",
                  "text/css"
                ]
              ],
              "status": 200,
              "status_text": ""
            },
            "http://localhost:8080/nbextensions/google.colab/tabbar_main.min.js": {
              "data": "Ly8gY2xhbmctZm9ybWF0IG9mZgooZnVuY3Rpb24oKXt2YXIgaCxhYT1mdW5jdGlvbihhKXt2YXIgYj0wO3JldHVybiBmdW5jdGlvbigpe3JldHVybiBiPGEubGVuZ3RoP3tkb25lOiExLHZhbHVlOmFbYisrXX06e2RvbmU6ITB9fX0sYmE9ZnVuY3Rpb24oYSl7dmFyIGI9InVuZGVmaW5lZCIhPXR5cGVvZiBTeW1ib2wmJlN5bWJvbC5pdGVyYXRvciYmYVtTeW1ib2wuaXRlcmF0b3JdO3JldHVybiBiP2IuY2FsbChhKTp7bmV4dDphYShhKX19LGw9dGhpc3x8c2VsZixjYT1mdW5jdGlvbigpe30sZGE9ZnVuY3Rpb24oYSl7YS5CYT12b2lkIDA7YS5SPWZ1bmN0aW9uKCl7cmV0dXJuIGEuQmE/YS5CYTphLkJhPW5ldyBhfX0sZWE9ZnVuY3Rpb24oYSl7dmFyIGI9dHlwZW9mIGE7aWYoIm9iamVjdCI9PWIpaWYoYSl7aWYoYSBpbnN0YW5jZW9mIEFycmF5KXJldHVybiJhcnJheSI7aWYoYSBpbnN0YW5jZW9mIE9iamVjdClyZXR1cm4gYjt2YXIgYz1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoYSk7aWYoIltvYmplY3QgV2luZG93XSI9PWMpcmV0dXJuIm9iamVjdCI7CmlmKCJbb2JqZWN0IEFycmF5XSI9PWN8fCJudW1iZXIiPT10eXBlb2YgYS5sZW5ndGgmJiJ1bmRlZmluZWQiIT10eXBlb2YgYS5zcGxpY2UmJiJ1bmRlZmluZWQiIT10eXBlb2YgYS5wcm9wZXJ0eUlzRW51bWVyYWJsZSYmIWEucHJvcGVydHlJc0VudW1lcmFibGUoInNwbGljZSIpKXJldHVybiJhcnJheSI7aWYoIltvYmplY3QgRnVuY3Rpb25dIj09Y3x8InVuZGVmaW5lZCIhPXR5cGVvZiBhLmNhbGwmJiJ1bmRlZmluZWQiIT10eXBlb2YgYS5wcm9wZXJ0eUlzRW51bWVyYWJsZSYmIWEucHJvcGVydHlJc0VudW1lcmFibGUoImNhbGwiKSlyZXR1cm4iZnVuY3Rpb24ifWVsc2UgcmV0dXJuIm51bGwiO2Vsc2UgaWYoImZ1bmN0aW9uIj09YiYmInVuZGVmaW5lZCI9PXR5cGVvZiBhLmNhbGwpcmV0dXJuIm9iamVjdCI7cmV0dXJuIGJ9LGZhPWZ1bmN0aW9uKGEpe3JldHVybiJhcnJheSI9PWVhKGEpfSxoYT1mdW5jdGlvbihhKXt2YXIgYj1lYShhKTtyZXR1cm4iYXJyYXkiPT1ifHwib2JqZWN0Ij09CmImJiJudW1iZXIiPT10eXBlb2YgYS5sZW5ndGh9LGlhPWZ1bmN0aW9uKGEpe3JldHVybiJmdW5jdGlvbiI9PWVhKGEpfSxtPWZ1bmN0aW9uKGEpe3ZhciBiPXR5cGVvZiBhO3JldHVybiJvYmplY3QiPT1iJiZudWxsIT1hfHwiZnVuY3Rpb24iPT1ifSxqYT0iY2xvc3VyZV91aWRfIisoMUU5Kk1hdGgucmFuZG9tKCk+Pj4wKSxrYT0wLGxhPWZ1bmN0aW9uKGEsYil7dmFyIGM9QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLDEpO3JldHVybiBmdW5jdGlvbigpe3ZhciBkPWMuc2xpY2UoKTtkLnB1c2guYXBwbHkoZCxhcmd1bWVudHMpO3JldHVybiBhLmFwcGx5KHRoaXMsZCl9fSxuPWZ1bmN0aW9uKGEsYil7ZnVuY3Rpb24gYygpe31jLnByb3RvdHlwZT1iLnByb3RvdHlwZTthLmk9Yi5wcm90b3R5cGU7YS5wcm90b3R5cGU9bmV3IGM7YS5wcm90b3R5cGUuY29uc3RydWN0b3I9YX07dmFyIG1hLG5hPXtlYjoiYWN0aXZlZGVzY2VuZGFudCIsamI6ImF0b21pYyIsa2I6ImF1dG9jb21wbGV0ZSIsbWI6ImJ1c3kiLHBiOiJjaGVja2VkIixxYjoiY29saW5kZXgiLHZiOiJjb250cm9scyIseGI6ImRlc2NyaWJlZGJ5IixBYjoiZGlzYWJsZWQiLENiOiJkcm9wZWZmZWN0IixEYjoiZXhwYW5kZWQiLEViOiJmbG93dG8iLEdiOiJncmFiYmVkIixLYjoiaGFzcG9wdXAiLE1iOiJoaWRkZW4iLE9iOiJpbnZhbGlkIixQYjoibGFiZWwiLFFiOiJsYWJlbGxlZGJ5IixSYjoibGV2ZWwiLFdiOiJsaXZlIixrYzoibXVsdGlsaW5lIixsYzoibXVsdGlzZWxlY3RhYmxlIixwYzoib3JpZW50YXRpb24iLHFjOiJvd25zIixyYzoicG9zaW5zZXQiLHRjOiJwcmVzc2VkIix4YzoicmVhZG9ubHkiLHpjOiJyZWxldmFudCIsQWM6InJlcXVpcmVkIixFYzoicm93aW5kZXgiLEhjOiJzZWxlY3RlZCIsSmM6InNldHNpemUiLExjOiJzb3J0IixaYzoidmFsdWVtYXgiLCRjOiJ2YWx1ZW1pbiIsYWQ6InZhbHVlbm93IiwKYmQ6InZhbHVldGV4dCJ9O3ZhciBvYT1mdW5jdGlvbihhLGIsYyl7Zm9yKHZhciBkIGluIGEpYi5jYWxsKGMsYVtkXSxkLGEpfSxwYT1mdW5jdGlvbihhLGIpe2Zvcih2YXIgYyBpbiBhKWlmKGFbY109PWIpcmV0dXJuITA7cmV0dXJuITF9LHFhPWZ1bmN0aW9uKGEsYixjKXtpZihudWxsIT09YSYmYiBpbiBhKXRocm93IEVycm9yKCdUaGUgb2JqZWN0IGFscmVhZHkgY29udGFpbnMgdGhlIGtleSAiJytiKyciJyk7YVtiXT1jfSxzYT1mdW5jdGlvbihhKXt2YXIgYj17fSxjO2ZvcihjIGluIGEpYlthW2NdXT1jO3JldHVybiBifSx0YT0iY29uc3RydWN0b3IgaGFzT3duUHJvcGVydHkgaXNQcm90b3R5cGVPZiBwcm9wZXJ0eUlzRW51bWVyYWJsZSB0b0xvY2FsZVN0cmluZyB0b1N0cmluZyB2YWx1ZU9mIi5zcGxpdCgiICIpLHVhPWZ1bmN0aW9uKGEsYil7Zm9yKHZhciBjLGQsZT0xO2U8YXJndW1lbnRzLmxlbmd0aDtlKyspe2Q9YXJndW1lbnRzW2VdO2ZvcihjIGluIGQpYVtjXT1kW2NdO2Zvcih2YXIgZj0wO2Y8dGEubGVuZ3RoO2YrKyljPQp0YVtmXSxPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoZCxjKSYmKGFbY109ZFtjXSl9fTt2YXIgdmE9e2ZiOiJhbGVydCIsZ2I6ImFsZXJ0ZGlhbG9nIixoYjoiYXBwbGljYXRpb24iLGliOiJhcnRpY2xlIixsYjoiYmFubmVyIixuYjoiYnV0dG9uIixvYjoiY2hlY2tib3giLHJiOiJjb2x1bW5oZWFkZXIiLHNiOiJjb21ib2JveCIsdGI6ImNvbXBsZW1lbnRhcnkiLHViOiJjb250ZW50aW5mbyIsd2I6ImRlZmluaXRpb24iLHliOiJkaWFsb2ciLHpiOiJkaXJlY3RvcnkiLEJiOiJkb2N1bWVudCIsRmI6ImZvcm0iLEhiOiJncmlkIixJYjoiZ3JpZGNlbGwiLEpiOiJncm91cCIsTGI6ImhlYWRpbmciLE5iOiJpbWciLFNiOiJsaW5rIixUYjoibGlzdCIsVWI6Imxpc3Rib3giLFZiOiJsaXN0aXRlbSIsWGI6ImxvZyIsWWI6Im1haW4iLFpiOiJtYXJxdWVlIiwkYjoibWF0aCIsYWM6Im1lbnUiLGJjOiJtZW51YmFyIixjYzoibWVudWl0ZW0iLGRjOiJtZW51aXRlbWNoZWNrYm94IixlYzoibWVudWl0ZW1yYWRpbyIsbWM6Im5hdmlnYXRpb24iLG5jOiJub3RlIixvYzoib3B0aW9uIiwKc2M6InByZXNlbnRhdGlvbiIsdWM6InByb2dyZXNzYmFyIix2YzoicmFkaW8iLHdjOiJyYWRpb2dyb3VwIix5YzoicmVnaW9uIixCYzoicm93IixDYzoicm93Z3JvdXAiLERjOiJyb3doZWFkZXIiLEZjOiJzY3JvbGxiYXIiLEdjOiJzZWFyY2giLEljOiJzZXBhcmF0b3IiLEtjOiJzbGlkZXIiLE1jOiJzcGluYnV0dG9uIixOYzoic3RhdHVzIixPYzoidGFiIixQYzoidGFibGlzdCIsUWM6InRhYnBhbmVsIixSYzoidGV4dGJveCIsU2M6InRleHRpbmZvIixUYzoidGltZXIiLFVjOiJ0b29sYmFyIixWYzoidG9vbHRpcCIsV2M6InRyZWUiLFhjOiJ0cmVlZ3JpZCIsWWM6InRyZWVpdGVtIn07dmFyIHdhPWZ1bmN0aW9uKGEpe2lmKEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKUVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsd2EpO2Vsc2V7dmFyIGI9RXJyb3IoKS5zdGFjaztiJiYodGhpcy5zdGFjaz1iKX1hJiYodGhpcy5tZXNzYWdlPVN0cmluZyhhKSl9O24od2EsRXJyb3IpO3dhLnByb3RvdHlwZS5uYW1lPSJDdXN0b21FcnJvciI7dmFyIHhhO3ZhciB5YT1mdW5jdGlvbihhLGIpe2E9YS5zcGxpdCgiJXMiKTtmb3IodmFyIGM9IiIsZD1hLmxlbmd0aC0xLGU9MDtlPGQ7ZSsrKWMrPWFbZV0rKGU8Yi5sZW5ndGg/YltlXToiJXMiKTt3YS5jYWxsKHRoaXMsYythW2RdKX07bih5YSx3YSk7eWEucHJvdG90eXBlLm5hbWU9IkFzc2VydGlvbkVycm9yIjsKdmFyIHphPWZ1bmN0aW9uKGEsYixjLGQpe3ZhciBlPSJBc3NlcnRpb24gZmFpbGVkIjtpZihjKXtlKz0iOiAiK2M7dmFyIGY9ZH1lbHNlIGEmJihlKz0iOiAiK2EsZj1iKTt0aHJvdyBuZXcgeWEoIiIrZSxmfHxbXSk7fSxxPWZ1bmN0aW9uKGEsYixjKXthfHx6YSgiIixudWxsLGIsQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLDIpKTtyZXR1cm4gYX0sQWE9ZnVuY3Rpb24oYSxiLGMpe20oYSkmJjE9PWEubm9kZVR5cGV8fHphKCJFeHBlY3RlZCBFbGVtZW50IGJ1dCBnb3QgJXM6ICVzLiIsW2VhKGEpLGFdLGIsQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLDIpKX0sQ2E9ZnVuY3Rpb24oYSxiLGMsZCl7YSBpbnN0YW5jZW9mIGJ8fHphKCJFeHBlY3RlZCBpbnN0YW5jZW9mICVzIGJ1dCBnb3QgJXMuIixbQmEoYiksQmEoYSldLGMsQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLDMpKX0sQmE9ZnVuY3Rpb24oYSl7cmV0dXJuIGEgaW5zdGFuY2VvZgpGdW5jdGlvbj9hLmRpc3BsYXlOYW1lfHxhLm5hbWV8fCJ1bmtub3duIHR5cGUgbmFtZSI6YSBpbnN0YW5jZW9mIE9iamVjdD9hLmNvbnN0cnVjdG9yLmRpc3BsYXlOYW1lfHxhLmNvbnN0cnVjdG9yLm5hbWV8fE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChhKTpudWxsPT09YT8ibnVsbCI6dHlwZW9mIGF9O3ZhciBEYT1BcnJheS5wcm90b3R5cGUuaW5kZXhPZj9mdW5jdGlvbihhLGIpe3EobnVsbCE9YS5sZW5ndGgpO3JldHVybiBBcnJheS5wcm90b3R5cGUuaW5kZXhPZi5jYWxsKGEsYix2b2lkIDApfTpmdW5jdGlvbihhLGIpe2lmKCJzdHJpbmciPT09dHlwZW9mIGEpcmV0dXJuInN0cmluZyIhPT10eXBlb2YgYnx8MSE9Yi5sZW5ndGg/LTE6YS5pbmRleE9mKGIsMCk7Zm9yKHZhciBjPTA7YzxhLmxlbmd0aDtjKyspaWYoYyBpbiBhJiZhW2NdPT09YilyZXR1cm4gYztyZXR1cm4tMX0scj1BcnJheS5wcm90b3R5cGUuZm9yRWFjaD9mdW5jdGlvbihhLGIsYyl7cShudWxsIT1hLmxlbmd0aCk7QXJyYXkucHJvdG90eXBlLmZvckVhY2guY2FsbChhLGIsYyl9OmZ1bmN0aW9uKGEsYixjKXtmb3IodmFyIGQ9YS5sZW5ndGgsZT0ic3RyaW5nIj09PXR5cGVvZiBhP2Euc3BsaXQoIiIpOmEsZj0wO2Y8ZDtmKyspZiBpbiBlJiZiLmNhbGwoYyxlW2ZdLGYsYSl9LEVhPUFycmF5LnByb3RvdHlwZS5maWx0ZXI/CmZ1bmN0aW9uKGEsYil7cShudWxsIT1hLmxlbmd0aCk7cmV0dXJuIEFycmF5LnByb3RvdHlwZS5maWx0ZXIuY2FsbChhLGIsdm9pZCAwKX06ZnVuY3Rpb24oYSxiKXtmb3IodmFyIGM9YS5sZW5ndGgsZD1bXSxlPTAsZj0ic3RyaW5nIj09PXR5cGVvZiBhP2Euc3BsaXQoIiIpOmEsZz0wO2c8YztnKyspaWYoZyBpbiBmKXt2YXIgaz1mW2ddO2IuY2FsbCh2b2lkIDAsayxnLGEpJiYoZFtlKytdPWspfXJldHVybiBkfSxGYT1BcnJheS5wcm90b3R5cGUuZXZlcnk/ZnVuY3Rpb24oYSxiKXtxKG51bGwhPWEubGVuZ3RoKTtyZXR1cm4gQXJyYXkucHJvdG90eXBlLmV2ZXJ5LmNhbGwoYSxiLHZvaWQgMCl9OmZ1bmN0aW9uKGEsYil7Zm9yKHZhciBjPWEubGVuZ3RoLGQ9InN0cmluZyI9PT10eXBlb2YgYT9hLnNwbGl0KCIiKTphLGU9MDtlPGM7ZSsrKWlmKGUgaW4gZCYmIWIuY2FsbCh2b2lkIDAsZFtlXSxlLGEpKXJldHVybiExO3JldHVybiEwfSxHYT1mdW5jdGlvbihhLGIpe3JldHVybiAwPD0KRGEoYSxiKX0sSGE9ZnVuY3Rpb24oYSxiKXtiPURhKGEsYik7dmFyIGM7aWYoYz0wPD1iKXEobnVsbCE9YS5sZW5ndGgpLEFycmF5LnByb3RvdHlwZS5zcGxpY2UuY2FsbChhLGIsMSk7cmV0dXJuIGN9LElhPWZ1bmN0aW9uKGEpe3JldHVybiBBcnJheS5wcm90b3R5cGUuY29uY2F0LmFwcGx5KFtdLGFyZ3VtZW50cyl9LEphPWZ1bmN0aW9uKGEpe3ZhciBiPWEubGVuZ3RoO2lmKDA8Yil7Zm9yKHZhciBjPUFycmF5KGIpLGQ9MDtkPGI7ZCsrKWNbZF09YVtkXTtyZXR1cm4gY31yZXR1cm5bXX0sTGE9ZnVuY3Rpb24oYSxiLGMsZCl7cShudWxsIT1hLmxlbmd0aCk7QXJyYXkucHJvdG90eXBlLnNwbGljZS5hcHBseShhLEthKGFyZ3VtZW50cywxKSl9LEthPWZ1bmN0aW9uKGEsYixjKXtxKG51bGwhPWEubGVuZ3RoKTtyZXR1cm4gMj49YXJndW1lbnRzLmxlbmd0aD9BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhLGIpOkFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGEsYixjKX07dmFyIE1hPVN0cmluZy5wcm90b3R5cGUudHJpbT9mdW5jdGlvbihhKXtyZXR1cm4gYS50cmltKCl9OmZ1bmN0aW9uKGEpe3JldHVybi9eW1xzXHhhMF0qKFtcc1xTXSo/KVtcc1x4YTBdKiQvLmV4ZWMoYSlbMV19LE5hPS8mL2csT2E9LzwvZyxQYT0vPi9nLFFhPS8iL2csUmE9LycvZyxTYT0vXHgwMC9nLFRhPS9bXHgwMCY8PiInXS8sdD1mdW5jdGlvbihhLGIpe3JldHVybi0xIT1hLmluZGV4T2YoYil9LFVhPWZ1bmN0aW9uKGEsYil7cmV0dXJuIGE8Yj8tMTphPmI/MTowfTt2YXIgdTthOnt2YXIgVmE9bC5uYXZpZ2F0b3I7aWYoVmEpe3ZhciBXYT1WYS51c2VyQWdlbnQ7aWYoV2Epe3U9V2E7YnJlYWsgYX19dT0iIn07LyoKCiBDb3B5cmlnaHQgVGhlIENsb3N1cmUgTGlicmFyeSBBdXRob3JzLgogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjAKKi8KdmFyIFhhPWZ1bmN0aW9uKGEpe1RhLnRlc3QoYSkmJigtMSE9YS5pbmRleE9mKCImIikmJihhPWEucmVwbGFjZShOYSwiJmFtcDsiKSksLTEhPWEuaW5kZXhPZigiPCIpJiYoYT1hLnJlcGxhY2UoT2EsIiZsdDsiKSksLTEhPWEuaW5kZXhPZigiPiIpJiYoYT1hLnJlcGxhY2UoUGEsIiZndDsiKSksLTEhPWEuaW5kZXhPZignIicpJiYoYT1hLnJlcGxhY2UoUWEsIiZxdW90OyIpKSwtMSE9YS5pbmRleE9mKCInIikmJihhPWEucmVwbGFjZShSYSwiJiMzOTsiKSksLTEhPWEuaW5kZXhPZigiXHgwMCIpJiYoYT1hLnJlcGxhY2UoU2EsIiYjMDsiKSkpO3JldHVybiBhfTt2YXIgWWE9ZnVuY3Rpb24oYSl7WWFbIiAiXShhKTtyZXR1cm4gYX07WWFbIiAiXT1jYTt2YXIgJGE9ZnVuY3Rpb24oYSxiKXt2YXIgYz1aYTtyZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGMsYSk/Y1thXTpjW2FdPWIoYSl9O3ZhciBhYj10KHUsIk9wZXJhIiksdj10KHUsIlRyaWRlbnQiKXx8dCh1LCJNU0lFIiksYmI9dCh1LCJFZGdlIikseD10KHUsIkdlY2tvIikmJiEodCh1LnRvTG93ZXJDYXNlKCksIndlYmtpdCIpJiYhdCh1LCJFZGdlIikpJiYhKHQodSwiVHJpZGVudCIpfHx0KHUsIk1TSUUiKSkmJiF0KHUsIkVkZ2UiKSx5PXQodS50b0xvd2VyQ2FzZSgpLCJ3ZWJraXQiKSYmIXQodSwiRWRnZSIpLHo9dCh1LCJNYWNpbnRvc2giKSxjYj1mdW5jdGlvbigpe3ZhciBhPWwuZG9jdW1lbnQ7cmV0dXJuIGE/YS5kb2N1bWVudE1vZGU6dm9pZCAwfSxkYjsKYTp7dmFyIGViPSIiLGZiPWZ1bmN0aW9uKCl7dmFyIGE9dTtpZih4KXJldHVybi9ydjooW15cKTtdKykoXCl8OykvLmV4ZWMoYSk7aWYoYmIpcmV0dXJuL0VkZ2VcLyhbXGRcLl0rKS8uZXhlYyhhKTtpZih2KXJldHVybi9cYig/Ok1TSUV8cnYpWzogXShbXlwpO10rKShcKXw7KS8uZXhlYyhhKTtpZih5KXJldHVybi9XZWJLaXRcLyhcUyspLy5leGVjKGEpO2lmKGFiKXJldHVybi8oPzpWZXJzaW9uKVsgXC9dPyhcUyspLy5leGVjKGEpfSgpO2ZiJiYoZWI9ZmI/ZmJbMV06IiIpO2lmKHYpe3ZhciBnYj1jYigpO2lmKG51bGwhPWdiJiZnYj5wYXJzZUZsb2F0KGViKSl7ZGI9U3RyaW5nKGdiKTticmVhayBhfX1kYj1lYn0KdmFyIGhiPWRiLFphPXt9LEE9ZnVuY3Rpb24oYSl7cmV0dXJuICRhKGEsZnVuY3Rpb24oKXtmb3IodmFyIGI9MCxjPU1hKFN0cmluZyhoYikpLnNwbGl0KCIuIiksZD1NYShTdHJpbmcoYSkpLnNwbGl0KCIuIiksZT1NYXRoLm1heChjLmxlbmd0aCxkLmxlbmd0aCksZj0wOzA9PWImJmY8ZTtmKyspe3ZhciBnPWNbZl18fCIiLGs9ZFtmXXx8IiI7ZG97Zz0vKFxkKikoXEQqKSguKikvLmV4ZWMoZyl8fFsiIiwiIiwiIiwiIl07az0vKFxkKikoXEQqKSguKikvLmV4ZWMoayl8fFsiIiwiIiwiIiwiIl07aWYoMD09Z1swXS5sZW5ndGgmJjA9PWtbMF0ubGVuZ3RoKWJyZWFrO2I9VWEoMD09Z1sxXS5sZW5ndGg/MDpwYXJzZUludChnWzFdLDEwKSwwPT1rWzFdLmxlbmd0aD8wOnBhcnNlSW50KGtbMV0sMTApKXx8VWEoMD09Z1syXS5sZW5ndGgsMD09a1syXS5sZW5ndGgpfHxVYShnWzJdLGtbMl0pO2c9Z1szXTtrPWtbM119d2hpbGUoMD09Yil9cmV0dXJuIDA8PWJ9KX0saWI7CmliPWwuZG9jdW1lbnQmJnY/Y2IoKTp2b2lkIDA7dmFyIGpiPSF2fHw5PD1OdW1iZXIoaWIpO3ZhciBsYj1mdW5jdGlvbihhLGIpe29hKGIsZnVuY3Rpb24oYyxkKXtjJiYib2JqZWN0Ij09dHlwZW9mIGMmJmMuZGQmJihjPWMuY2QoKSk7InN0eWxlIj09ZD9hLnN0eWxlLmNzc1RleHQ9YzoiY2xhc3MiPT1kP2EuY2xhc3NOYW1lPWM6ImZvciI9PWQ/YS5odG1sRm9yPWM6a2IuaGFzT3duUHJvcGVydHkoZCk/YS5zZXRBdHRyaWJ1dGUoa2JbZF0sYyk6MD09ZC5sYXN0SW5kZXhPZigiYXJpYS0iLDApfHwwPT1kLmxhc3RJbmRleE9mKCJkYXRhLSIsMCk/YS5zZXRBdHRyaWJ1dGUoZCxjKTphW2RdPWN9KX0sa2I9e2NlbGxwYWRkaW5nOiJjZWxsUGFkZGluZyIsY2VsbHNwYWNpbmc6ImNlbGxTcGFjaW5nIixjb2xzcGFuOiJjb2xTcGFuIixmcmFtZWJvcmRlcjoiZnJhbWVCb3JkZXIiLGhlaWdodDoiaGVpZ2h0IixtYXhsZW5ndGg6Im1heExlbmd0aCIsbm9uY2U6Im5vbmNlIixyb2xlOiJyb2xlIixyb3dzcGFuOiJyb3dTcGFuIix0eXBlOiJ0eXBlIix1c2VtYXA6InVzZU1hcCIsdmFsaWduOiJ2QWxpZ24iLAp3aWR0aDoid2lkdGgifSxtYj1mdW5jdGlvbihhLGIsYyl7ZnVuY3Rpb24gZChrKXtrJiZiLmFwcGVuZENoaWxkKCJzdHJpbmciPT09dHlwZW9mIGs/YS5jcmVhdGVUZXh0Tm9kZShrKTprKX1mb3IodmFyIGU9MjtlPGMubGVuZ3RoO2UrKyl7dmFyIGY9Y1tlXTtpZighaGEoZil8fG0oZikmJjA8Zi5ub2RlVHlwZSlkKGYpO2Vsc2V7YTp7aWYoZiYmIm51bWJlciI9PXR5cGVvZiBmLmxlbmd0aCl7aWYobShmKSl7dmFyIGc9ImZ1bmN0aW9uIj09dHlwZW9mIGYuaXRlbXx8InN0cmluZyI9PXR5cGVvZiBmLml0ZW07YnJlYWsgYX1pZihpYShmKSl7Zz0iZnVuY3Rpb24iPT10eXBlb2YgZi5pdGVtO2JyZWFrIGF9fWc9ITF9cihnP0phKGYpOmYsZCl9fX0sbmI9ZnVuY3Rpb24oYSxiKXtiPVN0cmluZyhiKTsiYXBwbGljYXRpb24veGh0bWwreG1sIj09PWEuY29udGVudFR5cGUmJihiPWIudG9Mb3dlckNhc2UoKSk7cmV0dXJuIGEuY3JlYXRlRWxlbWVudChiKX0sb2I9ZnVuY3Rpb24oYSl7YSYmCmEucGFyZW50Tm9kZSYmYS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGEpfSxwYj1mdW5jdGlvbihhLGIpe2lmKCFhfHwhYilyZXR1cm4hMTtpZihhLmNvbnRhaW5zJiYxPT1iLm5vZGVUeXBlKXJldHVybiBhPT1ifHxhLmNvbnRhaW5zKGIpO2lmKCJ1bmRlZmluZWQiIT10eXBlb2YgYS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbilyZXR1cm4gYT09Ynx8ISEoYS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbihiKSYxNik7Zm9yKDtiJiZhIT1iOyliPWIucGFyZW50Tm9kZTtyZXR1cm4gYj09YX0scWI9ZnVuY3Rpb24oYSl7cShhLCJOb2RlIGNhbm5vdCBiZSBudWxsIG9yIHVuZGVmaW5lZC4iKTtyZXR1cm4gOT09YS5ub2RlVHlwZT9hOmEub3duZXJEb2N1bWVudHx8YS5kb2N1bWVudH0scmI9ZnVuY3Rpb24oYSxiKXtiP2EudGFiSW5kZXg9MDooYS50YWJJbmRleD0tMSxhLnJlbW92ZUF0dHJpYnV0ZSgidGFiSW5kZXgiKSl9LHNiPWZ1bmN0aW9uKGEpe3JldHVybiB2JiYhQSgiOSIpPyhhPWEuZ2V0QXR0cmlidXRlTm9kZSgidGFiaW5kZXgiKSwKbnVsbCE9YSYmYS5zcGVjaWZpZWQpOmEuaGFzQXR0cmlidXRlKCJ0YWJpbmRleCIpfSx0Yj1mdW5jdGlvbihhKXthPWEudGFiSW5kZXg7cmV0dXJuIm51bWJlciI9PT10eXBlb2YgYSYmMDw9YSYmMzI3Njg+YX0sdWI9ZnVuY3Rpb24oYSl7dGhpcy5hPWF8fGwuZG9jdW1lbnR8fGRvY3VtZW50fTt1Yi5wcm90b3R5cGUuZj1mdW5jdGlvbihhKXtyZXR1cm4ic3RyaW5nIj09PXR5cGVvZiBhP3RoaXMuYS5nZXRFbGVtZW50QnlJZChhKTphfTsKdWIucHJvdG90eXBlLmI9ZnVuY3Rpb24oYSxiLGMpe3ZhciBkPXRoaXMuYSxlPWFyZ3VtZW50cyxmPVN0cmluZyhlWzBdKSxnPWVbMV07aWYoIWpiJiZnJiYoZy5uYW1lfHxnLnR5cGUpKXtmPVsiPCIsZl07Zy5uYW1lJiZmLnB1c2goJyBuYW1lPSInLFhhKGcubmFtZSksJyInKTtpZihnLnR5cGUpe2YucHVzaCgnIHR5cGU9IicsWGEoZy50eXBlKSwnIicpO3ZhciBrPXt9O3VhKGssZyk7ZGVsZXRlIGsudHlwZTtnPWt9Zi5wdXNoKCI+Iik7Zj1mLmpvaW4oIiIpfWY9bmIoZCxmKTtnJiYoInN0cmluZyI9PT10eXBlb2YgZz9mLmNsYXNzTmFtZT1nOmZhKGcpP2YuY2xhc3NOYW1lPWcuam9pbigiICIpOmxiKGYsZykpOzI8ZS5sZW5ndGgmJm1iKGQsZixlKTtyZXR1cm4gZn07dmFyIHZiPWZ1bmN0aW9uKGEsYil7Yj8ocShwYSh2YSxiKSwiTm8gc3VjaCBBUklBIHJvbGUgIitiKSxhLnNldEF0dHJpYnV0ZSgicm9sZSIsYikpOmEucmVtb3ZlQXR0cmlidXRlKCJyb2xlIil9LHhiPWZ1bmN0aW9uKGEsYixjKXtmYShjKSYmKGM9Yy5qb2luKCIgIikpO3ZhciBkPXdiKGIpOyIiPT09Y3x8dm9pZCAwPT1jPyhtYXx8KG1hPXthdG9taWM6ITEsYXV0b2NvbXBsZXRlOiJub25lIixkcm9wZWZmZWN0OiJub25lIixoYXNwb3B1cDohMSxsaXZlOiJvZmYiLG11bHRpbGluZTohMSxtdWx0aXNlbGVjdGFibGU6ITEsb3JpZW50YXRpb246InZlcnRpY2FsIixyZWFkb25seTohMSxyZWxldmFudDoiYWRkaXRpb25zIHRleHQiLHJlcXVpcmVkOiExLHNvcnQ6Im5vbmUiLGJ1c3k6ITEsZGlzYWJsZWQ6ITEsaGlkZGVuOiExLGludmFsaWQ6ImZhbHNlIn0pLGM9bWEsYiBpbiBjP2Euc2V0QXR0cmlidXRlKGQsY1tiXSk6YS5yZW1vdmVBdHRyaWJ1dGUoZCkpOmEuc2V0QXR0cmlidXRlKGQsCmMpfSx3Yj1mdW5jdGlvbihhKXtxKGEsIkFSSUEgYXR0cmlidXRlIGNhbm5vdCBiZSBlbXB0eS4iKTtxKHBhKG5hLGEpLCJObyBzdWNoIEFSSUEgYXR0cmlidXRlICIrYSk7cmV0dXJuImFyaWEtIithfTt2YXIgeWI9T2JqZWN0LmZyZWV6ZXx8ZnVuY3Rpb24oYSl7cmV0dXJuIGF9O3ZhciBDPWZ1bmN0aW9uKCl7dGhpcy5VPXRoaXMuVTt0aGlzLko9dGhpcy5KfTtDLnByb3RvdHlwZS5VPSExO0MucHJvdG90eXBlLk49ZnVuY3Rpb24oKXt0aGlzLlV8fCh0aGlzLlU9ITAsdGhpcy51KCkpfTt2YXIgemI9ZnVuY3Rpb24oYSxiKXthLlU/YigpOihhLkp8fChhLko9W10pLGEuSi5wdXNoKGIpKX07Qy5wcm90b3R5cGUudT1mdW5jdGlvbigpe2lmKHRoaXMuSilmb3IoO3RoaXMuSi5sZW5ndGg7KXRoaXMuSi5zaGlmdCgpKCl9O3ZhciBBYj1mdW5jdGlvbihhKXthJiYiZnVuY3Rpb24iPT10eXBlb2YgYS5OJiZhLk4oKX07dmFyIEJiPWZ1bmN0aW9uKGEpe3JldHVybiJzdHJpbmciPT10eXBlb2YgYS5jbGFzc05hbWU/YS5jbGFzc05hbWU6YS5nZXRBdHRyaWJ1dGUmJmEuZ2V0QXR0cmlidXRlKCJjbGFzcyIpfHwiIn0sRD1mdW5jdGlvbihhKXtyZXR1cm4gYS5jbGFzc0xpc3Q/YS5jbGFzc0xpc3Q6QmIoYSkubWF0Y2goL1xTKy9nKXx8W119LENiPWZ1bmN0aW9uKGEsYil7InN0cmluZyI9PXR5cGVvZiBhLmNsYXNzTmFtZT9hLmNsYXNzTmFtZT1iOmEuc2V0QXR0cmlidXRlJiZhLnNldEF0dHJpYnV0ZSgiY2xhc3MiLGIpfSxEYj1mdW5jdGlvbihhLGIpe3JldHVybiBhLmNsYXNzTGlzdD9hLmNsYXNzTGlzdC5jb250YWlucyhiKTpHYShEKGEpLGIpfSxFYj1mdW5jdGlvbihhLGIpe2lmKGEuY2xhc3NMaXN0KWEuY2xhc3NMaXN0LmFkZChiKTtlbHNlIGlmKCFEYihhLGIpKXt2YXIgYz1CYihhKTtDYihhLGMrKDA8Yy5sZW5ndGg/IiAiK2I6YikpfX0sRmI9ZnVuY3Rpb24oYSxiKXtpZihhLmNsYXNzTGlzdClyKGIsCmZ1bmN0aW9uKGUpe0ViKGEsZSl9KTtlbHNle3ZhciBjPXt9O3IoRChhKSxmdW5jdGlvbihlKXtjW2VdPSEwfSk7cihiLGZ1bmN0aW9uKGUpe2NbZV09ITB9KTtiPSIiO2Zvcih2YXIgZCBpbiBjKWIrPTA8Yi5sZW5ndGg/IiAiK2Q6ZDtDYihhLGIpfX0sR2I9ZnVuY3Rpb24oYSxiKXthLmNsYXNzTGlzdD9hLmNsYXNzTGlzdC5yZW1vdmUoYik6RGIoYSxiKSYmQ2IoYSxFYShEKGEpLGZ1bmN0aW9uKGMpe3JldHVybiBjIT1ifSkuam9pbigiICIpKX0sSGI9ZnVuY3Rpb24oYSxiKXthLmNsYXNzTGlzdD9yKGIsZnVuY3Rpb24oYyl7R2IoYSxjKX0pOkNiKGEsRWEoRChhKSxmdW5jdGlvbihjKXtyZXR1cm4hR2EoYixjKX0pLmpvaW4oIiAiKSl9O3ZhciBJYj0hdnx8OTw9TnVtYmVyKGliKSxKYj0hdnx8OTw9TnVtYmVyKGliKSxLYj12JiYhQSgiOSIpLExiPWZ1bmN0aW9uKCl7aWYoIWwuYWRkRXZlbnRMaXN0ZW5lcnx8IU9iamVjdC5kZWZpbmVQcm9wZXJ0eSlyZXR1cm4hMTt2YXIgYT0hMSxiPU9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwicGFzc2l2ZSIse2dldDpmdW5jdGlvbigpe2E9ITB9fSk7dHJ5e2wuYWRkRXZlbnRMaXN0ZW5lcigidGVzdCIsY2EsYiksbC5yZW1vdmVFdmVudExpc3RlbmVyKCJ0ZXN0IixjYSxiKX1jYXRjaChjKXt9cmV0dXJuIGF9KCk7dmFyIEU9ZnVuY3Rpb24oYSxiKXt0aGlzLnR5cGU9YTt0aGlzLmE9dGhpcy50YXJnZXQ9Yjt0aGlzLmg9ITE7dGhpcy5LYT0hMH07RS5wcm90b3R5cGUuaj1mdW5jdGlvbigpe3RoaXMuaD0hMH07RS5wcm90b3R5cGUuZz1mdW5jdGlvbigpe3RoaXMuS2E9ITF9O3ZhciBGPXtMOiJtb3VzZWRvd24iLE06Im1vdXNldXAiLGFhOiJtb3VzZWNhbmNlbCIsaGM6Im1vdXNlbW92ZSIsamM6Im1vdXNlb3ZlciIsaWM6Im1vdXNlb3V0IixmYzoibW91c2VlbnRlciIsZ2M6Im1vdXNlbGVhdmUifTt2YXIgRz1mdW5jdGlvbihhLGIpe0UuY2FsbCh0aGlzLGE/YS50eXBlOiIiKTt0aGlzLnJlbGF0ZWRUYXJnZXQ9dGhpcy5hPXRoaXMudGFyZ2V0PW51bGw7dGhpcy5idXR0b249dGhpcy5zY3JlZW5ZPXRoaXMuc2NyZWVuWD10aGlzLmNsaWVudFk9dGhpcy5jbGllbnRYPTA7dGhpcy5rZXk9IiI7dGhpcy5jPTA7dGhpcy5BPXRoaXMubWV0YUtleT10aGlzLnNoaWZ0S2V5PXRoaXMuYWx0S2V5PXRoaXMuY3RybEtleT0hMTt0aGlzLnBvaW50ZXJJZD0wO3RoaXMucG9pbnRlclR5cGU9IiI7dGhpcy5iPW51bGw7aWYoYSl7dmFyIGM9dGhpcy50eXBlPWEudHlwZSxkPWEuY2hhbmdlZFRvdWNoZXMmJmEuY2hhbmdlZFRvdWNoZXMubGVuZ3RoP2EuY2hhbmdlZFRvdWNoZXNbMF06bnVsbDt0aGlzLnRhcmdldD1hLnRhcmdldHx8YS5zcmNFbGVtZW50O3RoaXMuYT1iO2lmKGI9YS5yZWxhdGVkVGFyZ2V0KXtpZih4KXthOnt0cnl7WWEoYi5ub2RlTmFtZSk7dmFyIGU9ITA7YnJlYWsgYX1jYXRjaChmKXt9ZT0KITF9ZXx8KGI9bnVsbCl9fWVsc2UibW91c2VvdmVyIj09Yz9iPWEuZnJvbUVsZW1lbnQ6Im1vdXNlb3V0Ij09YyYmKGI9YS50b0VsZW1lbnQpO3RoaXMucmVsYXRlZFRhcmdldD1iO2Q/KHRoaXMuY2xpZW50WD12b2lkIDAhPT1kLmNsaWVudFg/ZC5jbGllbnRYOmQucGFnZVgsdGhpcy5jbGllbnRZPXZvaWQgMCE9PWQuY2xpZW50WT9kLmNsaWVudFk6ZC5wYWdlWSx0aGlzLnNjcmVlblg9ZC5zY3JlZW5YfHwwLHRoaXMuc2NyZWVuWT1kLnNjcmVlbll8fDApOih0aGlzLmNsaWVudFg9dm9pZCAwIT09YS5jbGllbnRYP2EuY2xpZW50WDphLnBhZ2VYLHRoaXMuY2xpZW50WT12b2lkIDAhPT1hLmNsaWVudFk/YS5jbGllbnRZOmEucGFnZVksdGhpcy5zY3JlZW5YPWEuc2NyZWVuWHx8MCx0aGlzLnNjcmVlblk9YS5zY3JlZW5ZfHwwKTt0aGlzLmJ1dHRvbj1hLmJ1dHRvbjt0aGlzLmM9YS5rZXlDb2RlfHwwO3RoaXMua2V5PWEua2V5fHwiIjt0aGlzLmN0cmxLZXk9YS5jdHJsS2V5O3RoaXMuYWx0S2V5PQphLmFsdEtleTt0aGlzLnNoaWZ0S2V5PWEuc2hpZnRLZXk7dGhpcy5tZXRhS2V5PWEubWV0YUtleTt0aGlzLkE9ej9hLm1ldGFLZXk6YS5jdHJsS2V5O3RoaXMucG9pbnRlcklkPWEucG9pbnRlcklkfHwwO3RoaXMucG9pbnRlclR5cGU9InN0cmluZyI9PT10eXBlb2YgYS5wb2ludGVyVHlwZT9hLnBvaW50ZXJUeXBlOk1iW2EucG9pbnRlclR5cGVdfHwiIjt0aGlzLmI9YTthLmRlZmF1bHRQcmV2ZW50ZWQmJnRoaXMuZygpfX07bihHLEUpO3ZhciBOYj15YihbMSw0LDJdKSxNYj15Yih7MjoidG91Y2giLDM6InBlbiIsNDoibW91c2UifSksT2I9ZnVuY3Rpb24oYSl7cmV0dXJuIEliPzA9PWEuYi5idXR0b246ImNsaWNrIj09YS50eXBlPyEwOiEhKGEuYi5idXR0b24mTmJbMF0pfTtHLnByb3RvdHlwZS5qPWZ1bmN0aW9uKCl7Ry5pLmouY2FsbCh0aGlzKTt0aGlzLmIuc3RvcFByb3BhZ2F0aW9uP3RoaXMuYi5zdG9wUHJvcGFnYXRpb24oKTp0aGlzLmIuY2FuY2VsQnViYmxlPSEwfTsKRy5wcm90b3R5cGUuZz1mdW5jdGlvbigpe0cuaS5nLmNhbGwodGhpcyk7dmFyIGE9dGhpcy5iO2lmKGEucHJldmVudERlZmF1bHQpYS5wcmV2ZW50RGVmYXVsdCgpO2Vsc2UgaWYoYS5yZXR1cm5WYWx1ZT0hMSxLYil0cnl7aWYoYS5jdHJsS2V5fHwxMTI8PWEua2V5Q29kZSYmMTIzPj1hLmtleUNvZGUpYS5rZXlDb2RlPS0xfWNhdGNoKGIpe319O3ZhciBQYj0iY2xvc3VyZV9saXN0ZW5hYmxlXyIrKDFFNipNYXRoLnJhbmRvbSgpfDApLFFiPWZ1bmN0aW9uKGEpe3JldHVybiEoIWF8fCFhW1BiXSl9LFJiPTA7dmFyIFNiPWZ1bmN0aW9uKGEsYixjLGQsZSl7dGhpcy5saXN0ZW5lcj1hO3RoaXMuYT1udWxsO3RoaXMuc3JjPWI7dGhpcy50eXBlPWM7dGhpcy5jYXB0dXJlPSEhZDt0aGlzLm1hPWU7dGhpcy5rZXk9KytSYjt0aGlzLlg9dGhpcy5oYT0hMX0sVGI9ZnVuY3Rpb24oYSl7YS5YPSEwO2EubGlzdGVuZXI9bnVsbDthLmE9bnVsbDthLnNyYz1udWxsO2EubWE9bnVsbH07dmFyIFViPWZ1bmN0aW9uKGEpe3RoaXMuc3JjPWE7dGhpcy5hPXt9O3RoaXMuYj0wfTtVYi5wcm90b3R5cGUuYWRkPWZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIGY9YS50b1N0cmluZygpO2E9dGhpcy5hW2ZdO2F8fChhPXRoaXMuYVtmXT1bXSx0aGlzLmIrKyk7dmFyIGc9VmIoYSxiLGQsZSk7LTE8Zz8oYj1hW2ddLGN8fChiLmhhPSExKSk6KGI9bmV3IFNiKGIsdGhpcy5zcmMsZiwhIWQsZSksYi5oYT1jLGEucHVzaChiKSk7cmV0dXJuIGJ9Owp2YXIgV2I9ZnVuY3Rpb24oYSxiKXt2YXIgYz1iLnR5cGU7YyBpbiBhLmEmJkhhKGEuYVtjXSxiKSYmKFRiKGIpLDA9PWEuYVtjXS5sZW5ndGgmJihkZWxldGUgYS5hW2NdLGEuYi0tKSl9LFhiPWZ1bmN0aW9uKGEsYixjLGQsZSl7YT1hLmFbYi50b1N0cmluZygpXTtiPS0xO2EmJihiPVZiKGEsYyxkLGUpKTtyZXR1cm4tMTxiP2FbYl06bnVsbH0sVmI9ZnVuY3Rpb24oYSxiLGMsZCl7Zm9yKHZhciBlPTA7ZTxhLmxlbmd0aDsrK2Upe3ZhciBmPWFbZV07aWYoIWYuWCYmZi5saXN0ZW5lcj09YiYmZi5jYXB0dXJlPT0hIWMmJmYubWE9PWQpcmV0dXJuIGV9cmV0dXJuLTF9O3ZhciBZYj0iY2xvc3VyZV9sbV8iKygxRTYqTWF0aC5yYW5kb20oKXwwKSxaYj17fSwkYj0wLGJjPWZ1bmN0aW9uKGEsYixjLGQsZSl7aWYoZCYmZC5vbmNlKXJldHVybiBhYyhhLGIsYyxkLGUpO2lmKGZhKGIpKXtmb3IodmFyIGY9MDtmPGIubGVuZ3RoO2YrKyliYyhhLGJbZl0sYyxkLGUpO3JldHVybiBudWxsfWM9Y2MoYyk7cmV0dXJuIFFiKGEpP2RjKGEsYixjLG0oZCk/ISFkLmNhcHR1cmU6ISFkLGUpOmVjKGEsYixjLCExLGQsZSl9LGVjPWZ1bmN0aW9uKGEsYixjLGQsZSxmKXtpZighYil0aHJvdyBFcnJvcigiSW52YWxpZCBldmVudCB0eXBlIik7dmFyIGc9bShlKT8hIWUuY2FwdHVyZTohIWUsaz1mYyhhKTtrfHwoYVtZYl09az1uZXcgVWIoYSkpO2M9ay5hZGQoYixjLGQsZyxmKTtpZihjLmEpcmV0dXJuIGM7ZD1nYygpO2MuYT1kO2Quc3JjPWE7ZC5saXN0ZW5lcj1jO2lmKGEuYWRkRXZlbnRMaXN0ZW5lcilMYnx8KGU9Zyksdm9pZCAwPT09ZSYmKGU9ITEpLGEuYWRkRXZlbnRMaXN0ZW5lcihiLnRvU3RyaW5nKCksCmQsZSk7ZWxzZSBpZihhLmF0dGFjaEV2ZW50KWEuYXR0YWNoRXZlbnQoaGMoYi50b1N0cmluZygpKSxkKTtlbHNlIGlmKGEuYWRkTGlzdGVuZXImJmEucmVtb3ZlTGlzdGVuZXIpcSgiY2hhbmdlIj09PWIsIk1lZGlhUXVlcnlMaXN0IG9ubHkgaGFzIGEgY2hhbmdlIGV2ZW50IiksYS5hZGRMaXN0ZW5lcihkKTtlbHNlIHRocm93IEVycm9yKCJhZGRFdmVudExpc3RlbmVyIGFuZCBhdHRhY2hFdmVudCBhcmUgdW5hdmFpbGFibGUuIik7JGIrKztyZXR1cm4gY30sZ2M9ZnVuY3Rpb24oKXt2YXIgYT1pYyxiPUpiP2Z1bmN0aW9uKGMpe3JldHVybiBhLmNhbGwoYi5zcmMsYi5saXN0ZW5lcixjKX06ZnVuY3Rpb24oYyl7Yz1hLmNhbGwoYi5zcmMsYi5saXN0ZW5lcixjKTtpZighYylyZXR1cm4gY307cmV0dXJuIGJ9LGFjPWZ1bmN0aW9uKGEsYixjLGQsZSl7aWYoZmEoYikpe2Zvcih2YXIgZj0wO2Y8Yi5sZW5ndGg7ZisrKWFjKGEsYltmXSxjLGQsZSk7cmV0dXJuIG51bGx9Yz1jYyhjKTtyZXR1cm4gUWIoYSk/CmEuaC5hZGQoU3RyaW5nKGIpLGMsITAsbShkKT8hIWQuY2FwdHVyZTohIWQsZSk6ZWMoYSxiLGMsITAsZCxlKX0samM9ZnVuY3Rpb24oYSxiLGMsZCxlKXtpZihmYShiKSlmb3IodmFyIGY9MDtmPGIubGVuZ3RoO2YrKylqYyhhLGJbZl0sYyxkLGUpO2Vsc2UgZD1tKGQpPyEhZC5jYXB0dXJlOiEhZCxjPWNjKGMpLFFiKGEpPyhhPWEuaCxiPVN0cmluZyhiKS50b1N0cmluZygpLGIgaW4gYS5hJiYoZj1hLmFbYl0sYz1WYihmLGMsZCxlKSwtMTxjJiYoVGIoZltjXSkscShudWxsIT1mLmxlbmd0aCksQXJyYXkucHJvdG90eXBlLnNwbGljZS5jYWxsKGYsYywxKSwwPT1mLmxlbmd0aCYmKGRlbGV0ZSBhLmFbYl0sYS5iLS0pKSkpOmEmJihhPWZjKGEpKSYmKGM9WGIoYSxiLGMsZCxlKSkmJmtjKGMpfSxrYz1mdW5jdGlvbihhKXtpZigibnVtYmVyIiE9PXR5cGVvZiBhJiZhJiYhYS5YKXt2YXIgYj1hLnNyYztpZihRYihiKSlXYihiLmgsYSk7ZWxzZXt2YXIgYz1hLnR5cGUsZD1hLmE7Yi5yZW1vdmVFdmVudExpc3RlbmVyPwpiLnJlbW92ZUV2ZW50TGlzdGVuZXIoYyxkLGEuY2FwdHVyZSk6Yi5kZXRhY2hFdmVudD9iLmRldGFjaEV2ZW50KGhjKGMpLGQpOmIuYWRkTGlzdGVuZXImJmIucmVtb3ZlTGlzdGVuZXImJmIucmVtb3ZlTGlzdGVuZXIoZCk7JGItLTsoYz1mYyhiKSk/KFdiKGMsYSksMD09Yy5iJiYoYy5zcmM9bnVsbCxiW1liXT1udWxsKSk6VGIoYSl9fX0saGM9ZnVuY3Rpb24oYSl7cmV0dXJuIGEgaW4gWmI/WmJbYV06WmJbYV09Im9uIithfSxtYz1mdW5jdGlvbihhLGIsYyxkKXt2YXIgZT0hMDtpZihhPWZjKGEpKWlmKGI9YS5hW2IudG9TdHJpbmcoKV0pZm9yKGI9Yi5jb25jYXQoKSxhPTA7YTxiLmxlbmd0aDthKyspe3ZhciBmPWJbYV07ZiYmZi5jYXB0dXJlPT1jJiYhZi5YJiYoZj1sYyhmLGQpLGU9ZSYmITEhPT1mKX1yZXR1cm4gZX0sbGM9ZnVuY3Rpb24oYSxiKXt2YXIgYz1hLmxpc3RlbmVyLGQ9YS5tYXx8YS5zcmM7YS5oYSYma2MoYSk7cmV0dXJuIGMuY2FsbChkLGIpfSxpYz1mdW5jdGlvbihhLApiKXtpZihhLlgpcmV0dXJuITA7aWYoIUpiKXtpZighYilhOntiPVsid2luZG93IiwiZXZlbnQiXTtmb3IodmFyIGM9bCxkPTA7ZDxiLmxlbmd0aDtkKyspaWYoYz1jW2JbZF1dLG51bGw9PWMpe2I9bnVsbDticmVhayBhfWI9Y31kPWI7Yj1uZXcgRyhkLHRoaXMpO2M9ITA7aWYoISgwPmQua2V5Q29kZXx8dm9pZCAwIT1kLnJldHVyblZhbHVlKSl7YTp7dmFyIGU9ITE7aWYoMD09ZC5rZXlDb2RlKXRyeXtkLmtleUNvZGU9LTE7YnJlYWsgYX1jYXRjaChnKXtlPSEwfWlmKGV8fHZvaWQgMD09ZC5yZXR1cm5WYWx1ZSlkLnJldHVyblZhbHVlPSEwfWQ9W107Zm9yKGU9Yi5hO2U7ZT1lLnBhcmVudE5vZGUpZC5wdXNoKGUpO2E9YS50eXBlO2ZvcihlPWQubGVuZ3RoLTE7IWIuaCYmMDw9ZTtlLS0pe2IuYT1kW2VdO3ZhciBmPW1jKGRbZV0sYSwhMCxiKTtjPWMmJmZ9Zm9yKGU9MDshYi5oJiZlPGQubGVuZ3RoO2UrKyliLmE9ZFtlXSxmPW1jKGRbZV0sYSwhMSxiKSxjPWMmJmZ9cmV0dXJuIGN9cmV0dXJuIGxjKGEsCm5ldyBHKGIsdGhpcykpfSxmYz1mdW5jdGlvbihhKXthPWFbWWJdO3JldHVybiBhIGluc3RhbmNlb2YgVWI/YTpudWxsfSxuYz0iX19jbG9zdXJlX2V2ZW50c19mbl8iKygxRTkqTWF0aC5yYW5kb20oKT4+PjApLGNjPWZ1bmN0aW9uKGEpe3EoYSwiTGlzdGVuZXIgY2FuIG5vdCBiZSBudWxsLiIpO2lmKGlhKGEpKXJldHVybiBhO3EoYS5oYW5kbGVFdmVudCwiQW4gb2JqZWN0IGxpc3RlbmVyIG11c3QgaGF2ZSBoYW5kbGVFdmVudCBtZXRob2QuIik7YVtuY118fChhW25jXT1mdW5jdGlvbihiKXtyZXR1cm4gYS5oYW5kbGVFdmVudChiKX0pO3JldHVybiBhW25jXX07dmFyIG9jPWZ1bmN0aW9uKGEpe0MuY2FsbCh0aGlzKTt0aGlzLmI9YTt0aGlzLmE9e319O24ob2MsQyk7CnZhciBwYz1bXSxIPWZ1bmN0aW9uKGEsYixjLGQpe2ZhKGMpfHwoYyYmKHBjWzBdPWMudG9TdHJpbmcoKSksYz1wYyk7Zm9yKHZhciBlPTA7ZTxjLmxlbmd0aDtlKyspe3ZhciBmPWJjKGIsY1tlXSxkfHxhLmhhbmRsZUV2ZW50LCExLGEuYnx8YSk7aWYoIWYpYnJlYWs7YS5hW2Yua2V5XT1mfXJldHVybiBhfSxxYz1mdW5jdGlvbihhLGIsYyxkLGUsZil7aWYoZmEoYykpZm9yKHZhciBnPTA7ZzxjLmxlbmd0aDtnKyspcWMoYSxiLGNbZ10sZCxlLGYpO2Vsc2UgZD1kfHxhLmhhbmRsZUV2ZW50LGU9bShlKT8hIWUuY2FwdHVyZTohIWUsZj1mfHxhLmJ8fGEsZD1jYyhkKSxlPSEhZSxjPVFiKGIpP1hiKGIuaCxTdHJpbmcoYyksZCxlLGYpOmI/KGI9ZmMoYikpP1hiKGIsYyxkLGUsZik6bnVsbDpudWxsLGMmJihrYyhjKSxkZWxldGUgYS5hW2Mua2V5XSk7cmV0dXJuIGF9LHJjPWZ1bmN0aW9uKGEpe29hKGEuYSxmdW5jdGlvbihiLGMpe3RoaXMuYS5oYXNPd25Qcm9wZXJ0eShjKSYma2MoYil9LAphKTthLmE9e319O29jLnByb3RvdHlwZS51PWZ1bmN0aW9uKCl7b2MuaS51LmNhbGwodGhpcyk7cmModGhpcyl9O29jLnByb3RvdHlwZS5oYW5kbGVFdmVudD1mdW5jdGlvbigpe3Rocm93IEVycm9yKCJFdmVudEhhbmRsZXIuaGFuZGxlRXZlbnQgbm90IGltcGxlbWVudGVkIik7fTt2YXIgST1mdW5jdGlvbigpe0MuY2FsbCh0aGlzKTt0aGlzLmg9bmV3IFViKHRoaXMpO3RoaXMuTWE9dGhpczt0aGlzLnBhPW51bGx9O24oSSxDKTtJLnByb3RvdHlwZVtQYl09ITA7SS5wcm90b3R5cGUucmE9ZnVuY3Rpb24oYSl7dGhpcy5wYT1hfTtJLnByb3RvdHlwZS5yZW1vdmVFdmVudExpc3RlbmVyPWZ1bmN0aW9uKGEsYixjLGQpe2pjKHRoaXMsYSxiLGMsZCl9Owp2YXIgdWM9ZnVuY3Rpb24oYSxiKXtzYyhhKTt2YXIgYz1hLnBhO2lmKGMpe3ZhciBkPVtdO2Zvcih2YXIgZT0xO2M7Yz1jLnBhKWQucHVzaChjKSxxKDFFMz4rK2UsImluZmluaXRlIGxvb3AiKX1hPWEuTWE7Yz1iLnR5cGV8fGI7InN0cmluZyI9PT10eXBlb2YgYj9iPW5ldyBFKGIsYSk6YiBpbnN0YW5jZW9mIEU/Yi50YXJnZXQ9Yi50YXJnZXR8fGE6KGU9YixiPW5ldyBFKGMsYSksdWEoYixlKSk7ZT0hMDtpZihkKWZvcih2YXIgZj1kLmxlbmd0aC0xOyFiLmgmJjA8PWY7Zi0tKXt2YXIgZz1iLmE9ZFtmXTtlPXRjKGcsYywhMCxiKSYmZX1iLmh8fChnPWIuYT1hLGU9dGMoZyxjLCEwLGIpJiZlLGIuaHx8KGU9dGMoZyxjLCExLGIpJiZlKSk7aWYoZClmb3IoZj0wOyFiLmgmJmY8ZC5sZW5ndGg7ZisrKWc9Yi5hPWRbZl0sZT10YyhnLGMsITEsYikmJmU7cmV0dXJuIGV9OwpJLnByb3RvdHlwZS51PWZ1bmN0aW9uKCl7SS5pLnUuY2FsbCh0aGlzKTtpZih0aGlzLmgpe3ZhciBhPXRoaXMuaCxiPTAsYztmb3IoYyBpbiBhLmEpe2Zvcih2YXIgZD1hLmFbY10sZT0wO2U8ZC5sZW5ndGg7ZSsrKSsrYixUYihkW2VdKTtkZWxldGUgYS5hW2NdO2EuYi0tfX10aGlzLnBhPW51bGx9O3ZhciBkYz1mdW5jdGlvbihhLGIsYyxkLGUpe3NjKGEpO3JldHVybiBhLmguYWRkKFN0cmluZyhiKSxjLCExLGQsZSl9LHRjPWZ1bmN0aW9uKGEsYixjLGQpe2I9YS5oLmFbU3RyaW5nKGIpXTtpZighYilyZXR1cm4hMDtiPWIuY29uY2F0KCk7Zm9yKHZhciBlPSEwLGY9MDtmPGIubGVuZ3RoOysrZil7dmFyIGc9YltmXTtpZihnJiYhZy5YJiZnLmNhcHR1cmU9PWMpe3ZhciBrPWcubGlzdGVuZXIscD1nLm1hfHxnLnNyYztnLmhhJiZXYihhLmgsZyk7ZT0hMSE9PWsuY2FsbChwLGQpJiZlfX1yZXR1cm4gZSYmMCE9ZC5LYX0sc2M9ZnVuY3Rpb24oYSl7cShhLmgsIkV2ZW50IHRhcmdldCBpcyBub3QgaW5pdGlhbGl6ZWQuIERpZCB5b3UgY2FsbCB0aGUgc3VwZXJjbGFzcyAoZ29vZy5ldmVudHMuRXZlbnRUYXJnZXQpIGNvbnN0cnVjdG9yPyIpfTt2YXIgeGM9ZnVuY3Rpb24oYSxiLGMsZCxlLGYpe2lmKHkmJiFBKCI1MjUiKSlyZXR1cm4hMDtpZih6JiZlKXJldHVybiB2YyhhKTtpZihlJiYhZClyZXR1cm4hMTtpZigheCl7Im51bWJlciI9PT10eXBlb2YgYiYmKGI9d2MoYikpO3ZhciBnPTE3PT1ifHwxOD09Ynx8eiYmOTE9PWI7aWYoKCFjfHx6KSYmZ3x8eiYmMTY9PWImJihkfHxmKSlyZXR1cm4hMX1pZigoeXx8YmIpJiZkJiZjKXN3aXRjaChhKXtjYXNlIDIyMDpjYXNlIDIxOTpjYXNlIDIyMTpjYXNlIDE5MjpjYXNlIDE4NjpjYXNlIDE4OTpjYXNlIDE4NzpjYXNlIDE4ODpjYXNlIDE5MDpjYXNlIDE5MTpjYXNlIDE5MjpjYXNlIDIyMjpyZXR1cm4hMX1pZih2JiZkJiZiPT1hKXJldHVybiExO3N3aXRjaChhKXtjYXNlIDEzOnJldHVybiB4P2Z8fGU/ITE6IShjJiZkKTohMDtjYXNlIDI3OnJldHVybiEoeXx8YmJ8fHgpfXJldHVybiB4JiYoZHx8ZXx8Zik/ITE6dmMoYSl9LHZjPWZ1bmN0aW9uKGEpe2lmKDQ4PD1hJiY1Nz49YXx8Cjk2PD1hJiYxMDY+PWF8fDY1PD1hJiY5MD49YXx8KHl8fGJiKSYmMD09YSlyZXR1cm4hMDtzd2l0Y2goYSl7Y2FzZSAzMjpjYXNlIDQzOmNhc2UgNjM6Y2FzZSA2NDpjYXNlIDEwNzpjYXNlIDEwOTpjYXNlIDExMDpjYXNlIDExMTpjYXNlIDE4NjpjYXNlIDU5OmNhc2UgMTg5OmNhc2UgMTg3OmNhc2UgNjE6Y2FzZSAxODg6Y2FzZSAxOTA6Y2FzZSAxOTE6Y2FzZSAxOTI6Y2FzZSAyMjI6Y2FzZSAyMTk6Y2FzZSAyMjA6Y2FzZSAyMjE6Y2FzZSAxNjM6Y2FzZSA1ODpyZXR1cm4hMDtjYXNlIDE3MzpyZXR1cm4geDtkZWZhdWx0OnJldHVybiExfX0sd2M9ZnVuY3Rpb24oYSl7aWYoeClhPXljKGEpO2Vsc2UgaWYoeiYmeSlzd2l0Y2goYSl7Y2FzZSA5MzphPTkxfXJldHVybiBhfSx5Yz1mdW5jdGlvbihhKXtzd2l0Y2goYSl7Y2FzZSA2MTpyZXR1cm4gMTg3O2Nhc2UgNTk6cmV0dXJuIDE4NjtjYXNlIDE3MzpyZXR1cm4gMTg5O2Nhc2UgMjI0OnJldHVybiA5MTtjYXNlIDA6cmV0dXJuIDIyNDsKZGVmYXVsdDpyZXR1cm4gYX19O3ZhciBKPWZ1bmN0aW9uKGEsYil7SS5jYWxsKHRoaXMpO2EmJnpjKHRoaXMsYSxiKX07bihKLEkpO2g9Si5wcm90b3R5cGU7aC5TPW51bGw7aC5uYT1udWxsO2guQ2E9bnVsbDtoLm9hPW51bGw7aC53PS0xO2guRj0tMTtoLnVhPSExOwp2YXIgQWM9ezM6MTMsMTI6MTQ0LDYzMjMyOjM4LDYzMjMzOjQwLDYzMjM0OjM3LDYzMjM1OjM5LDYzMjM2OjExMiw2MzIzNzoxMTMsNjMyMzg6MTE0LDYzMjM5OjExNSw2MzI0MDoxMTYsNjMyNDE6MTE3LDYzMjQyOjExOCw2MzI0MzoxMTksNjMyNDQ6MTIwLDYzMjQ1OjEyMSw2MzI0NjoxMjIsNjMyNDc6MTIzLDYzMjQ4OjQ0LDYzMjcyOjQ2LDYzMjczOjM2LDYzMjc1OjM1LDYzMjc2OjMzLDYzMjc3OjM0LDYzMjg5OjE0NCw2MzMwMjo0NX0sQmM9e1VwOjM4LERvd246NDAsTGVmdDozNyxSaWdodDozOSxFbnRlcjoxMyxGMToxMTIsRjI6MTEzLEYzOjExNCxGNDoxMTUsRjU6MTE2LEY2OjExNyxGNzoxMTgsRjg6MTE5LEY5OjEyMCxGMTA6MTIxLEYxMToxMjIsRjEyOjEyMywiVSswMDdGIjo0NixIb21lOjM2LEVuZDozNSxQYWdlVXA6MzMsUGFnZURvd246MzQsSW5zZXJ0OjQ1fSxDYz0heXx8QSgiNTI1IiksRGM9eiYmeDsKSi5wcm90b3R5cGUuYT1mdW5jdGlvbihhKXtpZih5fHxiYilpZigxNz09dGhpcy53JiYhYS5jdHJsS2V5fHwxOD09dGhpcy53JiYhYS5hbHRLZXl8fHomJjkxPT10aGlzLncmJiFhLm1ldGFLZXkpdGhpcy5GPXRoaXMudz0tMTstMT09dGhpcy53JiYoYS5jdHJsS2V5JiYxNyE9YS5jP3RoaXMudz0xNzphLmFsdEtleSYmMTghPWEuYz90aGlzLnc9MTg6YS5tZXRhS2V5JiY5MSE9YS5jJiYodGhpcy53PTkxKSk7Q2MmJiF4YyhhLmMsdGhpcy53LGEuc2hpZnRLZXksYS5jdHJsS2V5LGEuYWx0S2V5LGEubWV0YUtleSk/dGhpcy5oYW5kbGVFdmVudChhKToodGhpcy5GPXdjKGEuYyksRGMmJih0aGlzLnVhPWEuYWx0S2V5KSl9O0oucHJvdG90eXBlLmI9ZnVuY3Rpb24oYSl7dGhpcy5GPXRoaXMudz0tMTt0aGlzLnVhPWEuYWx0S2V5fTsKSi5wcm90b3R5cGUuaGFuZGxlRXZlbnQ9ZnVuY3Rpb24oYSl7dmFyIGI9YS5iLGM9Yi5hbHRLZXk7aWYodiYmImtleXByZXNzIj09YS50eXBlKXt2YXIgZD10aGlzLkY7dmFyIGU9MTMhPWQmJjI3IT1kP2Iua2V5Q29kZTowfWVsc2UoeXx8YmIpJiYia2V5cHJlc3MiPT1hLnR5cGU/KGQ9dGhpcy5GLGU9MDw9Yi5jaGFyQ29kZSYmNjMyMzI+Yi5jaGFyQ29kZSYmdmMoZCk/Yi5jaGFyQ29kZTowKTphYiYmIXk/KGQ9dGhpcy5GLGU9dmMoZCk/Yi5rZXlDb2RlOjApOigia2V5cHJlc3MiPT1hLnR5cGU/KERjJiYoYz10aGlzLnVhKSxiLmtleUNvZGU9PWIuY2hhckNvZGU/MzI+Yi5rZXlDb2RlPyhkPWIua2V5Q29kZSxlPTApOihkPXRoaXMuRixlPWIuY2hhckNvZGUpOihkPWIua2V5Q29kZXx8dGhpcy5GLGU9Yi5jaGFyQ29kZXx8MCkpOihkPWIua2V5Q29kZXx8dGhpcy5GLGU9Yi5jaGFyQ29kZXx8MCkseiYmNjM9PWUmJjIyND09ZCYmKGQ9MTkxKSk7dmFyIGY9ZD13YyhkKTtkPzYzMjMyPD0KZCYmZCBpbiBBYz9mPUFjW2RdOjI1PT1kJiZhLnNoaWZ0S2V5JiYoZj05KTpiLmtleUlkZW50aWZpZXImJmIua2V5SWRlbnRpZmllciBpbiBCYyYmKGY9QmNbYi5rZXlJZGVudGlmaWVyXSk7eCYmQ2MmJiJrZXlwcmVzcyI9PWEudHlwZSYmIXhjKGYsdGhpcy53LGEuc2hpZnRLZXksYS5jdHJsS2V5LGMsYS5tZXRhS2V5KXx8KGE9Zj09dGhpcy53LHRoaXMudz1mLGI9bmV3IEVjKGYsZSxhLGIpLGIuYWx0S2V5PWMsdWModGhpcyxiKSl9O0oucHJvdG90eXBlLmY9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5TfTsKdmFyIHpjPWZ1bmN0aW9uKGEsYixjKXthLm9hJiZGYyhhKTthLlM9YjthLm5hPWJjKGEuUywia2V5cHJlc3MiLGEsYyk7YS5DYT1iYyhhLlMsImtleWRvd24iLGEuYSxjLGEpO2Eub2E9YmMoYS5TLCJrZXl1cCIsYS5iLGMsYSl9LEZjPWZ1bmN0aW9uKGEpe2EubmEmJihrYyhhLm5hKSxrYyhhLkNhKSxrYyhhLm9hKSxhLm5hPW51bGwsYS5DYT1udWxsLGEub2E9bnVsbCk7YS5TPW51bGw7YS53PS0xO2EuRj0tMX07Si5wcm90b3R5cGUudT1mdW5jdGlvbigpe0ouaS51LmNhbGwodGhpcyk7RmModGhpcyl9O3ZhciBFYz1mdW5jdGlvbihhLGIsYyxkKXtHLmNhbGwodGhpcyxkKTt0aGlzLnR5cGU9ImtleSI7dGhpcy5jPWE7dGhpcy5yZXBlYXQ9Y307bihFYyxHKTt2YXIgR2M9eD8iTW96VXNlclNlbGVjdCI6eXx8YmI/IldlYmtpdFVzZXJTZWxlY3QiOm51bGwsSGM9ZnVuY3Rpb24oYSxiKXtiPWI/bnVsbDphLmdldEVsZW1lbnRzQnlUYWdOYW1lKCIqIik7aWYoR2Mpe3ZhciBjPSJub25lIjthLnN0eWxlJiYoYS5zdHlsZVtHY109Yyk7aWYoYil7YT0wO2Zvcih2YXIgZDtkPWJbYV07YSsrKWQuc3R5bGUmJihkLnN0eWxlW0djXT1jKX19ZWxzZSBpZih2fHxhYilpZihjPSJvbiIsYS5zZXRBdHRyaWJ1dGUoInVuc2VsZWN0YWJsZSIsYyksYilmb3IoYT0wO2Q9YlthXTthKyspZC5zZXRBdHRyaWJ1dGUoInVuc2VsZWN0YWJsZSIsYyl9O3ZhciBJYz1mdW5jdGlvbigpe307ZGEoSWMpO0ljLnByb3RvdHlwZS5hPTA7dmFyIEs9ZnVuY3Rpb24oYSl7SS5jYWxsKHRoaXMpO3RoaXMuaj1hfHx4YXx8KHhhPW5ldyB1Yik7dGhpcy5xYT1KYzt0aGlzLlk9bnVsbDt0aGlzLm09ITE7dGhpcy5hPW51bGw7dGhpcy5BPXZvaWQgMDt0aGlzLmc9dGhpcy5jPXRoaXMuYj1udWxsO3RoaXMuR2E9ITF9O24oSyxJKTtLLnByb3RvdHlwZS5PYT1JYy5SKCk7CnZhciBKYz1udWxsLEtjPWZ1bmN0aW9uKGEsYil7c3dpdGNoKGEpe2Nhc2UgMTpyZXR1cm4gYj8iZGlzYWJsZSI6ImVuYWJsZSI7Y2FzZSAyOnJldHVybiBiPyJoaWdobGlnaHQiOiJ1bmhpZ2hsaWdodCI7Y2FzZSA0OnJldHVybiBiPyJhY3RpdmF0ZSI6ImRlYWN0aXZhdGUiO2Nhc2UgODpyZXR1cm4gYj8ic2VsZWN0IjoidW5zZWxlY3QiO2Nhc2UgMTY6cmV0dXJuIGI/ImNoZWNrIjoidW5jaGVjayI7Y2FzZSAzMjpyZXR1cm4gYj8iZm9jdXMiOiJibHVyIjtjYXNlIDY0OnJldHVybiBiPyJvcGVuIjoiY2xvc2UifXRocm93IEVycm9yKCJJbnZhbGlkIGNvbXBvbmVudCBzdGF0ZSIpO30sTGM9ZnVuY3Rpb24oYSl7cmV0dXJuIGEuWXx8KGEuWT0iOiIrKGEuT2EuYSsrKS50b1N0cmluZygzNikpfSxNYz1mdW5jdGlvbihhLGIpe2lmKGEuYiYmYS5iLmcpe3ZhciBjPWEuYi5nLGQ9YS5ZO2QgaW4gYyYmZGVsZXRlIGNbZF07cWEoYS5iLmcsYixhKX1hLlk9Yn07Sy5wcm90b3R5cGUuZj1mdW5jdGlvbigpe3JldHVybiB0aGlzLmF9Owp2YXIgTmM9ZnVuY3Rpb24oYSl7YT1hLmE7cShhLCJDYW4gbm90IGNhbGwgZ2V0RWxlbWVudFN0cmljdCBiZWZvcmUgcmVuZGVyaW5nL2RlY29yYXRpbmcuIik7cmV0dXJuIGF9LE9jPWZ1bmN0aW9uKGEpe2EuQXx8KGEuQT1uZXcgb2MoYSkpO3JldHVybiBxKGEuQSl9O0sucHJvdG90eXBlLnJhPWZ1bmN0aW9uKGEpe2lmKHRoaXMuYiYmdGhpcy5iIT1hKXRocm93IEVycm9yKCJNZXRob2Qgbm90IHN1cHBvcnRlZCIpO0suaS5yYS5jYWxsKHRoaXMsYSl9O0sucHJvdG90eXBlLmlhPWZ1bmN0aW9uKCl7dGhpcy5hPW5iKHRoaXMuai5hLCJESVYiKX07CnZhciBQYz1mdW5jdGlvbihhLGIpe2lmKGEubSl0aHJvdyBFcnJvcigiQ29tcG9uZW50IGFscmVhZHkgcmVuZGVyZWQiKTtpZihiJiZhLnhhKGIpKXthLkdhPSEwO3ZhciBjPXFiKGIpO2EuaiYmYS5qLmE9PWN8fChhLmo9Yj9uZXcgdWIocWIoYikpOnhhfHwoeGE9bmV3IHViKSk7YS52YShiKTthLkQoKX1lbHNlIHRocm93IEVycm9yKCJJbnZhbGlkIGVsZW1lbnQgdG8gZGVjb3JhdGUiKTt9O2g9Sy5wcm90b3R5cGU7aC54YT1mdW5jdGlvbigpe3JldHVybiEwfTtoLnZhPWZ1bmN0aW9uKGEpe3RoaXMuYT1hfTtoLkQ9ZnVuY3Rpb24oKXt0aGlzLm09ITA7UWModGhpcyxmdW5jdGlvbihhKXshYS5tJiZhLmYoKSYmYS5EKCl9KX07aC5QPWZ1bmN0aW9uKCl7UWModGhpcyxmdW5jdGlvbihhKXthLm0mJmEuUCgpfSk7dGhpcy5BJiZyYyh0aGlzLkEpO3RoaXMubT0hMX07CmgudT1mdW5jdGlvbigpe3RoaXMubSYmdGhpcy5QKCk7dGhpcy5BJiYodGhpcy5BLk4oKSxkZWxldGUgdGhpcy5BKTtRYyh0aGlzLGZ1bmN0aW9uKGEpe2EuTigpfSk7IXRoaXMuR2EmJnRoaXMuYSYmb2IodGhpcy5hKTt0aGlzLmI9dGhpcy5hPXRoaXMuZz10aGlzLmM9bnVsbDtLLmkudS5jYWxsKHRoaXMpfTtoLnNhPWZ1bmN0aW9uKGEsYil7dGhpcy50YShhLFJjKHRoaXMpLGIpfTsKaC50YT1mdW5jdGlvbihhLGIsYyl7cSghIWEsIlByb3ZpZGVkIGVsZW1lbnQgbXVzdCBub3QgYmUgbnVsbC4iKTtpZihhLm0mJihjfHwhdGhpcy5tKSl0aHJvdyBFcnJvcigiQ29tcG9uZW50IGFscmVhZHkgcmVuZGVyZWQiKTtpZigwPmJ8fGI+UmModGhpcykpdGhyb3cgRXJyb3IoIkNoaWxkIGNvbXBvbmVudCBpbmRleCBvdXQgb2YgYm91bmRzIik7dGhpcy5nJiZ0aGlzLmN8fCh0aGlzLmc9e30sdGhpcy5jPVtdKTtpZihhLmI9PXRoaXMpe3ZhciBkPUxjKGEpO3RoaXMuZ1tkXT1hO0hhKHRoaXMuYyxhKX1lbHNlIHFhKHRoaXMuZyxMYyhhKSxhKTtpZihhPT10aGlzKXRocm93IEVycm9yKCJVbmFibGUgdG8gc2V0IHBhcmVudCBjb21wb25lbnQiKTtpZihkPXRoaXMmJmEuYiYmYS5ZKXt2YXIgZT1hLmI7ZD1hLlk7ZS5nJiZkPyhlPWUuZyxkPShudWxsIT09ZSYmZCBpbiBlP2VbZF06dm9pZCAwKXx8bnVsbCk6ZD1udWxsfWlmKGQmJmEuYiE9dGhpcyl0aHJvdyBFcnJvcigiVW5hYmxlIHRvIHNldCBwYXJlbnQgY29tcG9uZW50Iik7CmEuYj10aGlzO0suaS5yYS5jYWxsKGEsdGhpcyk7TGEodGhpcy5jLGIsMCxhKTtpZihhLm0mJnRoaXMubSYmYS5iPT10aGlzKWM9dGhpcy5qYSgpLGI9Yy5jaGlsZE5vZGVzW2JdfHxudWxsLGIhPWEuZigpJiZjLmluc2VydEJlZm9yZShhLmYoKSxiKTtlbHNlIGlmKGMpe3RoaXMuYXx8dGhpcy5pYSgpO2M9TCh0aGlzLGIrMSk7Yj10aGlzLmphKCk7Yz1jP2MuYTpudWxsO2lmKGEubSl0aHJvdyBFcnJvcigiQ29tcG9uZW50IGFscmVhZHkgcmVuZGVyZWQiKTthLmF8fGEuaWEoKTtiP2IuaW5zZXJ0QmVmb3JlKGEuYSxjfHxudWxsKTphLmouYS5ib2R5LmFwcGVuZENoaWxkKGEuYSk7YS5iJiYhYS5iLm18fGEuRCgpfWVsc2UgdGhpcy5tJiYhYS5tJiZhLmEmJmEuYS5wYXJlbnROb2RlJiYxPT1hLmEucGFyZW50Tm9kZS5ub2RlVHlwZSYmYS5EKCl9O2guamE9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5hfTsKdmFyIFNjPWZ1bmN0aW9uKGEpe2lmKG51bGw9PWEucWEpe3ZhciBiPWEubT9hLmE6YS5qLmEuYm9keTthOnt2YXIgYz1xYihiKTtpZihjLmRlZmF1bHRWaWV3JiZjLmRlZmF1bHRWaWV3LmdldENvbXB1dGVkU3R5bGUmJihjPWMuZGVmYXVsdFZpZXcuZ2V0Q29tcHV0ZWRTdHlsZShiLG51bGwpKSl7Yz1jLmRpcmVjdGlvbnx8Yy5nZXRQcm9wZXJ0eVZhbHVlKCJkaXJlY3Rpb24iKXx8IiI7YnJlYWsgYX1jPSIifWEucWE9InJ0bCI9PShjfHwoYi5jdXJyZW50U3R5bGU/Yi5jdXJyZW50U3R5bGUuZGlyZWN0aW9uOm51bGwpfHxiLnN0eWxlJiZiLnN0eWxlLmRpcmVjdGlvbil9cmV0dXJuIGEucWF9LFJjPWZ1bmN0aW9uKGEpe3JldHVybiBhLmM/YS5jLmxlbmd0aDowfSxMPWZ1bmN0aW9uKGEsYil7cmV0dXJuIGEuYz9hLmNbYl18fG51bGw6bnVsbH0sUWM9ZnVuY3Rpb24oYSxiLGMpe2EuYyYmcihhLmMsYixjKX0sVGM9ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYS5jJiZiP0RhKGEuYyxiKTotMX07dmFyIFZjPWZ1bmN0aW9uKGEsYil7aWYoIWEpdGhyb3cgRXJyb3IoIkludmFsaWQgY2xhc3MgbmFtZSAiK2EpO2lmKCFpYShiKSl0aHJvdyBFcnJvcigiSW52YWxpZCBkZWNvcmF0b3IgZnVuY3Rpb24gIitiKTtVY1thXT1ifSxXYz17fSxVYz17fTt2YXIgWGM9ZnVuY3Rpb24oYSl7dGhpcy5oPWF9O2RhKFhjKTt2YXIgWWM9ZnVuY3Rpb24oYSxiKXthJiYoYS50YWJJbmRleD1iPzA6LTEpfSwkYz1mdW5jdGlvbihhLGIsYyl7Yy5pZCYmTWMoYixjLmlkKTt2YXIgZD1hLmIoKSxlPSExLGY9RChjKTtmJiZyKGYsZnVuY3Rpb24oZyl7Zz09ZD9lPSEwOmcmJnRoaXMuZyhiLGcsZCl9LGEpO2V8fEViKGMsZCk7WmMoYixjKTtyZXR1cm4gY307WGMucHJvdG90eXBlLmc9ZnVuY3Rpb24oYSxiLGMpe2I9PWMrIi1kaXNhYmxlZCI/YS5aKCExKTpiPT1jKyItaG9yaXpvbnRhbCI/YWQoYSwiaG9yaXpvbnRhbCIpOmI9PWMrIi12ZXJ0aWNhbCImJmFkKGEsInZlcnRpY2FsIil9Owp2YXIgWmM9ZnVuY3Rpb24oYSxiKXtpZihiKWZvcih2YXIgYz1iLmZpcnN0Q2hpbGQsZDtjJiZjLnBhcmVudE5vZGU9PWI7KXtkPWMubmV4dFNpYmxpbmc7aWYoMT09Yy5ub2RlVHlwZSl7YTp7dmFyIGU9YztxKGUpO2U9RChlKTtmb3IodmFyIGY9MCxnPWUubGVuZ3RoO2Y8ZztmKyspe3ZhciBrPWVbZl07aWYoaz1rIGluIFVjP1VjW2tdKCk6bnVsbCl7ZT1rO2JyZWFrIGF9fWU9bnVsbH1lJiYoZS5hPWMsYS5pc0VuYWJsZWQoKXx8ZS5aKCExKSxhLnNhKGUpLFBjKGUsYykpfWVsc2UgYy5ub2RlVmFsdWUmJiIiIT1NYShjLm5vZGVWYWx1ZSl8fGIucmVtb3ZlQ2hpbGQoYyk7Yz1kfX0sYmQ9ZnVuY3Rpb24oYSxiKXtiPWIuZigpO3EoYiwiVGhlIGNvbnRhaW5lciBET00gZWxlbWVudCBjYW5ub3QgYmUgbnVsbC4iKTtIYyhiLHgpO3YmJihiLmhpZGVGb2N1cz0hMCk7KGE9YS5oKSYmdmIoYixhKX07WGMucHJvdG90eXBlLmI9ZnVuY3Rpb24oKXtyZXR1cm4iZ29vZy1jb250YWluZXIifTsKWGMucHJvdG90eXBlLmM9ZnVuY3Rpb24oYSl7dmFyIGI9dGhpcy5iKCksYz1bYiwiaG9yaXpvbnRhbCI9PWEuSD9iKyItaG9yaXpvbnRhbCI6YisiLXZlcnRpY2FsIl07YS5pc0VuYWJsZWQoKXx8Yy5wdXNoKGIrIi1kaXNhYmxlZCIpO3JldHVybiBjfTt2YXIgTT1mdW5jdGlvbigpe30sY2Q7ZGEoTSk7dmFyIGRkPXtidXR0b246InByZXNzZWQiLGNoZWNrYm94OiJjaGVja2VkIixtZW51aXRlbToic2VsZWN0ZWQiLG1lbnVpdGVtY2hlY2tib3g6ImNoZWNrZWQiLG1lbnVpdGVtcmFkaW86ImNoZWNrZWQiLHJhZGlvOiJjaGVja2VkIix0YWI6InNlbGVjdGVkIix0cmVlaXRlbToic2VsZWN0ZWQifTtNLnByb3RvdHlwZS5oPWZ1bmN0aW9uKCl7fTtNLnByb3RvdHlwZS5jPWZ1bmN0aW9uKGEpe3JldHVybiBhLmouYigiRElWIixlZCh0aGlzLGEpLmpvaW4oIiAiKSxhLmJhKX07dmFyIGdkPWZ1bmN0aW9uKGEsYixjKXtpZihhPWEuZj9hLmYoKTphKXt2YXIgZD1bYl07diYmIUEoIjciKSYmKGQ9ZmQoRChhKSxiKSxkLnB1c2goYikpOyhjP0ZiOkhiKShhLGQpfX07Ck0ucHJvdG90eXBlLmc9ZnVuY3Rpb24oYSxiKXtiLmlkJiZNYyhhLGIuaWQpO2ImJmIuZmlyc3RDaGlsZD9oZChhLGIuZmlyc3RDaGlsZC5uZXh0U2libGluZz9KYShiLmNoaWxkTm9kZXMpOmIuZmlyc3RDaGlsZCk6YS5iYT1udWxsO3ZhciBjPTAsZD10aGlzLmEoKSxlPXRoaXMuYSgpLGY9ITEsZz0hMSxrPSExLHA9SmEoRChiKSk7cihwLGZ1bmN0aW9uKEIpe2Z8fEIhPWQ/Z3x8QiE9ZT9jfD1pZCh0aGlzLEIpOmc9ITA6KGY9ITAsZT09ZCYmKGc9ITApKTsxPT1pZCh0aGlzLEIpJiYoQWEoYiksc2IoYikmJnRiKGIpJiZyYihiLCExKSl9LHRoaXMpO2Eubz1jO2Z8fChwLnB1c2goZCksZT09ZCYmKGc9ITApKTtnfHxwLnB1c2goZSk7KGE9YS53YSkmJnAucHVzaC5hcHBseShwLGEpO2lmKHYmJiFBKCI3Iikpe3ZhciB3PWZkKHApOzA8dy5sZW5ndGgmJihwLnB1c2guYXBwbHkocCx3KSxrPSEwKX1mJiZnJiYhYSYmIWt8fENiKGIscC5qb2luKCIgIikpO3JldHVybiBifTsKdmFyIGpkPWZ1bmN0aW9uKGEsYil7aWYoYT1hLmgoKSl7cShiLCJUaGUgZWxlbWVudCBwYXNzZWQgYXMgYSBmaXJzdCBwYXJhbWV0ZXIgY2Fubm90IGJlIG51bGwuIik7dmFyIGM9Yi5nZXRBdHRyaWJ1dGUoInJvbGUiKXx8bnVsbDthIT1jJiZ2YihiLGEpfX0sa2Q9ZnVuY3Rpb24oYSxiKXt2YXIgYztpZihhLnYmMzImJihjPWEuZigpKSl7aWYoIWImJmEubyYzMil7dHJ5e2MuYmx1cigpfWNhdGNoKGQpe31hLm8mMzImJmEuRmEobnVsbCl9KHNiKGMpJiZ0YihjKSkhPWImJnJiKGMsYil9fSxsZD1mdW5jdGlvbihhLGIsYyl7Y2R8fChjZD17MToiZGlzYWJsZWQiLDg6InNlbGVjdGVkIiwxNjoiY2hlY2tlZCIsNjQ6ImV4cGFuZGVkIn0pO3EoYSwiVGhlIGVsZW1lbnQgcGFzc2VkIGFzIGEgZmlyc3QgcGFyYW1ldGVyIGNhbm5vdCBiZSBudWxsLiIpO2I9Y2RbYl07dmFyIGQ9YS5nZXRBdHRyaWJ1dGUoInJvbGUiKXx8bnVsbDtkJiYoZD1kZFtkXXx8YixiPSJjaGVja2VkIj09Ynx8InNlbGVjdGVkIj09CmI/ZDpiKTtiJiZ4YihhLGIsYyl9O00ucHJvdG90eXBlLmE9ZnVuY3Rpb24oKXtyZXR1cm4iZ29vZy1jb250cm9sIn07CnZhciBlZD1mdW5jdGlvbihhLGIpe3ZhciBjPWEuYSgpLGQ9W2NdLGU9YS5hKCk7ZSE9YyYmZC5wdXNoKGUpO2M9Yi5vO2ZvcihlPVtdO2M7KXt2YXIgZj1jJi1jO2UucHVzaChtZChhLGYpKTtjJj1+Zn1kLnB1c2guYXBwbHkoZCxlKTsoYT1iLndhKSYmZC5wdXNoLmFwcGx5KGQsYSk7diYmIUEoIjciKSYmZC5wdXNoLmFwcGx5KGQsZmQoZCkpO3JldHVybiBkfSxmZD1mdW5jdGlvbihhLGIpe3ZhciBjPVtdO2ImJihhPUlhKGEsW2JdKSk7cihbXSxmdW5jdGlvbihkKXshRmEoZCxsYShHYSxhKSl8fGImJiFHYShkLGIpfHxjLnB1c2goZC5qb2luKCJfIikpfSk7cmV0dXJuIGN9LG1kPWZ1bmN0aW9uKGEsYil7YS5ifHxuZChhKTtyZXR1cm4gYS5iW2JdfSxpZD1mdW5jdGlvbihhLGIpe2Euanx8KGEuYnx8bmQoYSksYS5qPXNhKGEuYikpO2E9cGFyc2VJbnQoYS5qW2JdLDEwKTtyZXR1cm4gaXNOYU4oYSk/MDphfSxuZD1mdW5jdGlvbihhKXt2YXIgYj1hLmEoKSxjPSF0KGIucmVwbGFjZSgvXHhhMHxccy9nLAoiICIpLCIgIik7cShjLCJDb250cm9sUmVuZGVyZXIgaGFzIGFuIGludmFsaWQgY3NzIGNsYXNzOiAnIitiKyInIik7YS5iPXsxOmIrIi1kaXNhYmxlZCIsMjpiKyItaG92ZXIiLDQ6YisiLWFjdGl2ZSIsODpiKyItc2VsZWN0ZWQiLDE2OmIrIi1jaGVja2VkIiwzMjpiKyItZm9jdXNlZCIsNjQ6YisiLW9wZW4ifX07dmFyIE49ZnVuY3Rpb24oYSxiLGMpe0suY2FsbCh0aGlzLGMpO2lmKCFiKXtiPXRoaXMuY29uc3RydWN0b3I7Zm9yKHZhciBkO2I7KXtkPWJbamFdfHwoYltqYV09KytrYSk7aWYoZD1XY1tkXSlicmVhaztiPWIuaT9iLmkuY29uc3RydWN0b3I6bnVsbH1iPWQ/aWEoZC5SKT9kLlIoKTpuZXcgZDpudWxsfXRoaXMuQj1iO3RoaXMuYmE9dm9pZCAwIT09YT9hOm51bGx9O24oTixLKTtoPU4ucHJvdG90eXBlO2guYmE9bnVsbDtoLm89MDtoLnY9Mzk7aC5LPTA7aC5JYT0hMDtoLndhPW51bGw7aC55YT0hMDtoLmlhPWZ1bmN0aW9uKCl7dmFyIGE9dGhpcy5CLmModGhpcyk7dGhpcy5hPWE7amQodGhpcy5CLGEpO0hjKGEsIXYmJiFhYik7dGhpcy5pc1Zpc2libGUoKXx8KGEuc3R5bGUuZGlzcGxheT0ibm9uZSIsYSYmeGIoYSwiaGlkZGVuIiwhMCkpfTtoLmphPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZigpfTtoLnhhPWZ1bmN0aW9uKCl7cmV0dXJuITB9OwpoLnZhPWZ1bmN0aW9uKGEpe3RoaXMuYT1hPXRoaXMuQi5nKHRoaXMsYSk7amQodGhpcy5CLGEpO0hjKGEsIXYmJiFhYik7dGhpcy5JYT0ibm9uZSIhPWEuc3R5bGUuZGlzcGxheX07CmguRD1mdW5jdGlvbigpe04uaS5ELmNhbGwodGhpcyk7dmFyIGE9TmModGhpcyk7cSh0aGlzKTtxKGEpO3RoaXMuaXNWaXNpYmxlKCl8fHhiKGEsImhpZGRlbiIsIXRoaXMuaXNWaXNpYmxlKCkpO3RoaXMuaXNFbmFibGVkKCl8fGxkKGEsMSwhdGhpcy5pc0VuYWJsZWQoKSk7dGhpcy52JjgmJmxkKGEsOCwhISh0aGlzLm8mOCkpO3RoaXMudiYxNiYmbGQoYSwxNiwhISh0aGlzLm8mMTYpKTt0aGlzLnYmNjQmJmxkKGEsNjQsISEodGhpcy5vJjY0KSk7YT10aGlzLkI7U2ModGhpcykmJmdkKHRoaXMuZigpLGEuYSgpKyItcnRsIiwhMCk7dGhpcy5pc0VuYWJsZWQoKSYma2QodGhpcyx0aGlzLmlzVmlzaWJsZSgpKTtpZih0aGlzLnYmLTImJih0aGlzLnlhJiZvZCh0aGlzLCEwKSx0aGlzLnYmMzImJihhPXRoaXMuZigpKSkpe3ZhciBiPXRoaXMuV3x8KHRoaXMuVz1uZXcgSik7emMoYixhKTtIKEgoSChPYyh0aGlzKSxiLCJrZXkiLHRoaXMuZmEpLGEsImZvY3VzIix0aGlzLk5hKSxhLCJibHVyIiwKdGhpcy5GYSl9fTt2YXIgb2Q9ZnVuY3Rpb24oYSxiKXt2YXIgYz1PYyhhKSxkPWEuZigpO2I/KEgoSChIKEgoYyxkLEYuTCxhLmthKSxkLFtGLk0sRi5hYV0sYS5sYSksZCwibW91c2VvdmVyIixhLkFhKSxkLCJtb3VzZW91dCIsYS56YSksYS5lYSE9Y2EmJkgoYyxkLCJjb250ZXh0bWVudSIsYS5lYSksdiYmKEEoOSl8fEgoYyxkLCJkYmxjbGljayIsYS5KYSksYS5nYXx8KGEuZ2E9bmV3IHBkKGEpLHpiKGEsbGEoQWIsYS5nYSkpKSkpOihxYyhxYyhxYyhxYyhjLGQsRi5MLGEua2EpLGQsW0YuTSxGLmFhXSxhLmxhKSxkLCJtb3VzZW92ZXIiLGEuQWEpLGQsIm1vdXNlb3V0IixhLnphKSxhLmVhIT1jYSYmcWMoYyxkLCJjb250ZXh0bWVudSIsYS5lYSksdiYmKEEoOSl8fHFjKGMsZCwiZGJsY2xpY2siLGEuSmEpLEFiKGEuZ2EpLGEuZ2E9bnVsbCkpfTsKTi5wcm90b3R5cGUuUD1mdW5jdGlvbigpe04uaS5QLmNhbGwodGhpcyk7dGhpcy5XJiZGYyh0aGlzLlcpO3RoaXMuaXNWaXNpYmxlKCkmJnRoaXMuaXNFbmFibGVkKCkmJmtkKHRoaXMsITEpfTtOLnByb3RvdHlwZS51PWZ1bmN0aW9uKCl7Ti5pLnUuY2FsbCh0aGlzKTt0aGlzLlcmJih0aGlzLlcuTigpLGRlbGV0ZSB0aGlzLlcpO2RlbGV0ZSB0aGlzLkI7dGhpcy5nYT10aGlzLndhPXRoaXMuYmE9bnVsbH07dmFyIGhkPWZ1bmN0aW9uKGEsYil7YS5iYT1ifTtOLnByb3RvdHlwZS5pc1Zpc2libGU9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5JYX07Ti5wcm90b3R5cGUuaXNFbmFibGVkPWZ1bmN0aW9uKCl7cmV0dXJuISh0aGlzLm8mMSl9OwpOLnByb3RvdHlwZS5aPWZ1bmN0aW9uKGEpe3ZhciBiPXRoaXMuYjtiJiYiZnVuY3Rpb24iPT10eXBlb2YgYi5pc0VuYWJsZWQmJiFiLmlzRW5hYmxlZCgpfHwhTyh0aGlzLDEsIWEpfHwoYXx8KHFkKHRoaXMsITEpLFAodGhpcywhMSkpLHRoaXMuaXNWaXNpYmxlKCkmJmtkKHRoaXMsYSksUSh0aGlzLDEsIWEsITApKX07CnZhciBQPWZ1bmN0aW9uKGEsYil7TyhhLDIsYikmJlEoYSwyLGIpfSxxZD1mdW5jdGlvbihhLGIpe08oYSw0LGIpJiZRKGEsNCxiKX0scmQ9ZnVuY3Rpb24oYSxiKXtPKGEsOCxiKSYmUShhLDgsYil9LHNkPWZ1bmN0aW9uKGEsYil7TyhhLDY0LGIpJiZRKGEsNjQsYil9LFE9ZnVuY3Rpb24oYSxiLGMsZCl7aWYoIWQmJjE9PWIpYS5aKCFjKTtlbHNlIGlmKGEudiZiJiZjIT0hIShhLm8mYikpe3ZhciBlPWEuQjtpZihkPWEuZigpKShlPW1kKGUsYikpJiZnZChhLGUsYyksbGQoZCxiLGMpO2Eubz1jP2Eub3xiOmEubyZ+Yn19LHRkPWZ1bmN0aW9uKGEsYixjKXtpZihhLm0mJmEubyZiJiYhYyl0aHJvdyBFcnJvcigiQ29tcG9uZW50IGFscmVhZHkgcmVuZGVyZWQiKTshYyYmYS5vJmImJlEoYSxiLCExKTthLnY9Yz9hLnZ8YjphLnYmfmJ9LFI9ZnVuY3Rpb24oYSxiKXtyZXR1cm4hISgyNTUmYikmJiEhKGEudiZiKX0sTz1mdW5jdGlvbihhLGIsYyl7cmV0dXJuISEoYS52JmIpJiYhIShhLm8mCmIpIT1jJiYoIShhLksmYil8fHVjKGEsS2MoYixjKSkpJiYhYS5VfTtoPU4ucHJvdG90eXBlO2guQWE9ZnVuY3Rpb24oYSl7KCFhLnJlbGF0ZWRUYXJnZXR8fCFwYih0aGlzLmYoKSxhLnJlbGF0ZWRUYXJnZXQpKSYmdWModGhpcywiZW50ZXIiKSYmdGhpcy5pc0VuYWJsZWQoKSYmUih0aGlzLDIpJiZQKHRoaXMsITApfTtoLnphPWZ1bmN0aW9uKGEpe2EucmVsYXRlZFRhcmdldCYmcGIodGhpcy5mKCksYS5yZWxhdGVkVGFyZ2V0KXx8IXVjKHRoaXMsImxlYXZlIil8fChSKHRoaXMsNCkmJnFkKHRoaXMsITEpLFIodGhpcywyKSYmUCh0aGlzLCExKSl9O2guZWE9Y2E7Cmgua2E9ZnVuY3Rpb24oYSl7aWYodGhpcy5pc0VuYWJsZWQoKSYmKFIodGhpcywyKSYmUCh0aGlzLCEwKSxPYihhKSYmISh5JiZ6JiZhLmN0cmxLZXkpKSl7Uih0aGlzLDQpJiZxZCh0aGlzLCEwKTt2YXIgYjtpZihiPXRoaXMuQil7dmFyIGM7Yj10aGlzLnYmMzImJihjPXRoaXMuZigpKT9zYihjKSYmdGIoYyk6ITF9YiYmdGhpcy5mKCkuZm9jdXMoKX0hT2IoYSl8fHkmJnomJmEuY3RybEtleXx8YS5nKCl9O2gubGE9ZnVuY3Rpb24oYSl7dGhpcy5pc0VuYWJsZWQoKSYmKFIodGhpcywyKSYmUCh0aGlzLCEwKSx0aGlzLm8mNCYmdWQodGhpcyxhKSYmUih0aGlzLDQpJiZxZCh0aGlzLCExKSl9O2guSmE9ZnVuY3Rpb24oYSl7dGhpcy5pc0VuYWJsZWQoKSYmdWQodGhpcyxhKX07CnZhciB1ZD1mdW5jdGlvbihhLGIpe2lmKFIoYSwxNikpe3ZhciBjPSEoYS5vJjE2KTtPKGEsMTYsYykmJlEoYSwxNixjKX1SKGEsOCkmJnJkKGEsITApO1IoYSw2NCkmJnNkKGEsIShhLm8mNjQpKTtjPW5ldyBFKCJhY3Rpb24iLGEpO2ImJihjLmFsdEtleT1iLmFsdEtleSxjLmN0cmxLZXk9Yi5jdHJsS2V5LGMubWV0YUtleT1iLm1ldGFLZXksYy5zaGlmdEtleT1iLnNoaWZ0S2V5LGMuQT1iLkEpO3JldHVybiB1YyhhLGMpfTtOLnByb3RvdHlwZS5OYT1mdW5jdGlvbigpe1IodGhpcywzMikmJk8odGhpcywzMiwhMCkmJlEodGhpcywzMiwhMCl9O04ucHJvdG90eXBlLkZhPWZ1bmN0aW9uKCl7Uih0aGlzLDQpJiZxZCh0aGlzLCExKTtSKHRoaXMsMzIpJiZPKHRoaXMsMzIsITEpJiZRKHRoaXMsMzIsITEpfTsKTi5wcm90b3R5cGUuZmE9ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuaXNWaXNpYmxlKCkmJnRoaXMuaXNFbmFibGVkKCkmJjEzPT1hLmMmJnVkKHRoaXMsYSk/KGEuZygpLGEuaigpLCEwKTohMX07aWYoIWlhKE4pKXRocm93IEVycm9yKCJJbnZhbGlkIGNvbXBvbmVudCBjbGFzcyAiK04pO2lmKCFpYShNKSl0aHJvdyBFcnJvcigiSW52YWxpZCByZW5kZXJlciBjbGFzcyAiK00pO3ZhciB2ZD1OW2phXXx8KE5bamFdPSsra2EpO1djW3ZkXT1NO1ZjKCJnb29nLWNvbnRyb2wiLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBOKG51bGwpfSk7dmFyIHBkPWZ1bmN0aW9uKGEpe0MuY2FsbCh0aGlzKTt0aGlzLmI9YTt0aGlzLmE9ITE7dGhpcy5jPW5ldyBvYyh0aGlzKTt6Yih0aGlzLGxhKEFiLHRoaXMuYykpO2E9TmModGhpcy5iKTtIKEgoSCh0aGlzLmMsYSxGLkwsdGhpcy5oKSxhLEYuTSx0aGlzLmopLGEsImNsaWNrIix0aGlzLmcpfTtuKHBkLEMpO3ZhciB3ZD0hdnx8OTw9TnVtYmVyKGliKTsKcGQucHJvdG90eXBlLmg9ZnVuY3Rpb24oKXt0aGlzLmE9ITF9O3BkLnByb3RvdHlwZS5qPWZ1bmN0aW9uKCl7dGhpcy5hPSEwfTt2YXIgeGQ9ZnVuY3Rpb24oYSxiKXtpZighd2QpcmV0dXJuIGEuYnV0dG9uPTAsYS50eXBlPWIsYTt2YXIgYz1kb2N1bWVudC5jcmVhdGVFdmVudCgiTW91c2VFdmVudHMiKTtjLmluaXRNb3VzZUV2ZW50KGIsYS5idWJibGVzLGEuY2FuY2VsYWJsZSxhLnZpZXd8fG51bGwsYS5kZXRhaWwsYS5zY3JlZW5YLGEuc2NyZWVuWSxhLmNsaWVudFgsYS5jbGllbnRZLGEuY3RybEtleSxhLmFsdEtleSxhLnNoaWZ0S2V5LGEubWV0YUtleSwwLGEucmVsYXRlZFRhcmdldHx8bnVsbCk7cmV0dXJuIGN9OwpwZC5wcm90b3R5cGUuZz1mdW5jdGlvbihhKXtpZih0aGlzLmEpdGhpcy5hPSExO2Vsc2V7dmFyIGI9YS5iLGM9Yi5idXR0b24sZD1iLnR5cGUsZT14ZChiLCJtb3VzZWRvd24iKTt0aGlzLmIua2EobmV3IEcoZSxhLmEpKTtlPXhkKGIsIm1vdXNldXAiKTt0aGlzLmIubGEobmV3IEcoZSxhLmEpKTt3ZHx8KGIuYnV0dG9uPWMsYi50eXBlPWQpfX07cGQucHJvdG90eXBlLnU9ZnVuY3Rpb24oKXt0aGlzLmI9bnVsbDtwZC5pLnUuY2FsbCh0aGlzKX07dmFyIFM9ZnVuY3Rpb24oYSxiLGMpe0suY2FsbCh0aGlzLGMpO3RoaXMuZGE9Ynx8WGMuUigpO3RoaXMuSD1hfHwidmVydGljYWwifTtuKFMsSyk7aD1TLnByb3RvdHlwZTtoLkRhPW51bGw7aC5jYT1udWxsO2guZGE9bnVsbDtoLkg9bnVsbDtoLlQ9ITA7aC5PPSEwO2gubD0tMTtoLnM9bnVsbDtoLlY9ITE7aC5JPW51bGw7dmFyIHlkPWZ1bmN0aW9uKGEpe3JldHVybiBhLkRhfHxhLmYoKX07aD1TLnByb3RvdHlwZTtoLmlhPWZ1bmN0aW9uKCl7dGhpcy5hPXRoaXMuai5iKCJESVYiLHRoaXMuZGEuYyh0aGlzKS5qb2luKCIgIikpfTtoLmphPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZigpfTtoLnhhPWZ1bmN0aW9uKGEpe3JldHVybiJESVYiPT1hLnRhZ05hbWV9O2gudmE9ZnVuY3Rpb24oYSl7dGhpcy5hPSRjKHRoaXMuZGEsdGhpcyxhKTsibm9uZSI9PWEuc3R5bGUuZGlzcGxheSYmKHRoaXMuVD0hMSl9OwpoLkQ9ZnVuY3Rpb24oKXtTLmkuRC5jYWxsKHRoaXMpO1FjKHRoaXMsZnVuY3Rpb24oYil7Yi5tJiZ6ZCh0aGlzLGIpfSx0aGlzKTt2YXIgYT10aGlzLmYoKTtiZCh0aGlzLmRhLHRoaXMpO0FkKHRoaXMsdGhpcy5UKTtIKEgoSChIKEgoSChIKEgoT2ModGhpcyksdGhpcywiZW50ZXIiLHRoaXMuV2EpLHRoaXMsImhpZ2hsaWdodCIsdGhpcy5YYSksdGhpcywidW5oaWdobGlnaHQiLHRoaXMuY2IpLHRoaXMsIm9wZW4iLHRoaXMuWWEpLHRoaXMsImNsb3NlIix0aGlzLlVhKSxhLEYuTCx0aGlzLlNhKSxxYihhKSxbRi5NLEYuYWFdLHRoaXMuVmEpLGEsW0YuTCxGLk0sRi5hYSwibW91c2VvdmVyIiwibW91c2VvdXQiLCJjb250ZXh0bWVudSJdLHRoaXMuVGEpO0JkKHRoaXMpfTt2YXIgQmQ9ZnVuY3Rpb24oYSl7dmFyIGI9T2MoYSksYz15ZChhKTtIKEgoSChiLGMsImZvY3VzIixhLkhhKSxjLCJibHVyIixhLlFhKSxhLmNhfHwoYS5jYT1uZXcgSih5ZChhKSkpLCJrZXkiLGEuUmEpfTtoPVMucHJvdG90eXBlOwpoLlA9ZnVuY3Rpb24oKXtDZCh0aGlzLC0xKTt0aGlzLnMmJnNkKHRoaXMucywhMSk7dGhpcy5WPSExO1MuaS5QLmNhbGwodGhpcyl9O2gudT1mdW5jdGlvbigpe1MuaS51LmNhbGwodGhpcyk7dGhpcy5jYSYmKHRoaXMuY2EuTigpLHRoaXMuY2E9bnVsbCk7dGhpcy5kYT10aGlzLnM9dGhpcy5JPXRoaXMuRGE9bnVsbH07aC5XYT1mdW5jdGlvbigpe3JldHVybiEwfTsKaC5YYT1mdW5jdGlvbihhKXt2YXIgYj1UYyh0aGlzLGEudGFyZ2V0KTtpZigtMTxiJiZiIT10aGlzLmwpe3ZhciBjPUwodGhpcyx0aGlzLmwpO2MmJlAoYywhMSk7dGhpcy5sPWI7Yz1MKHRoaXMsdGhpcy5sKTt0aGlzLlYmJnFkKGMsITApO3RoaXMucyYmYyE9dGhpcy5zJiYoYy52JjY0P3NkKGMsITApOnNkKHRoaXMucywhMSkpfWI9dGhpcy5mKCk7cShiLCJUaGUgRE9NIGVsZW1lbnQgZm9yIHRoZSBjb250YWluZXIgY2Fubm90IGJlIG51bGwuIik7bnVsbCE9YS50YXJnZXQuZigpJiZ4YihiLCJhY3RpdmVkZXNjZW5kYW50IixhLnRhcmdldC5mKCkuaWQpfTtoLmNiPWZ1bmN0aW9uKGEpe2EudGFyZ2V0PT1MKHRoaXMsdGhpcy5sKSYmKHRoaXMubD0tMSk7YT10aGlzLmYoKTtxKGEsIlRoZSBET00gZWxlbWVudCBmb3IgdGhlIGNvbnRhaW5lciBjYW5ub3QgYmUgbnVsbC4iKTthLnJlbW92ZUF0dHJpYnV0ZSh3YigiYWN0aXZlZGVzY2VuZGFudCIpKX07CmguWWE9ZnVuY3Rpb24oYSl7KGE9YS50YXJnZXQpJiZhIT10aGlzLnMmJmEuYj09dGhpcyYmKHRoaXMucyYmc2QodGhpcy5zLCExKSx0aGlzLnM9YSl9O2guVWE9ZnVuY3Rpb24oYSl7YS50YXJnZXQ9PXRoaXMucyYmKHRoaXMucz1udWxsKTt2YXIgYj10aGlzLmYoKSxjPWEudGFyZ2V0LmYoKTtiJiZhLnRhcmdldC5vJjImJmMmJihhPSIiLGMmJihhPWMuaWQscShhLCJUaGUgYWN0aXZlIGVsZW1lbnQgc2hvdWxkIGhhdmUgYW4gaWQuIikpLHhiKGIsImFjdGl2ZWRlc2NlbmRhbnQiLGEpKX07aC5TYT1mdW5jdGlvbihhKXt0aGlzLk8mJih0aGlzLlY9ITApO3ZhciBiPXlkKHRoaXMpO2ImJnNiKGIpJiZ0YihiKT9iLmZvY3VzKCk6YS5nKCl9O2guVmE9ZnVuY3Rpb24oKXt0aGlzLlY9ITF9OwpoLlRhPWZ1bmN0aW9uKGEpe2E6e3ZhciBiPWEudGFyZ2V0O2lmKHRoaXMuSSlmb3IodmFyIGM9dGhpcy5mKCk7YiYmYiE9PWM7KXt2YXIgZD1iLmlkO2lmKGQgaW4gdGhpcy5JKXtiPXRoaXMuSVtkXTticmVhayBhfWI9Yi5wYXJlbnROb2RlfWI9bnVsbH1pZihiKXN3aXRjaChhLnR5cGUpe2Nhc2UgRi5MOmIua2EoYSk7YnJlYWs7Y2FzZSBGLk06Y2FzZSBGLmFhOmIubGEoYSk7YnJlYWs7Y2FzZSAibW91c2VvdmVyIjpiLkFhKGEpO2JyZWFrO2Nhc2UgIm1vdXNlb3V0IjpiLnphKGEpO2JyZWFrO2Nhc2UgImNvbnRleHRtZW51IjpiLmVhKGEpfX07aC5IYT1mdW5jdGlvbigpe307aC5RYT1mdW5jdGlvbigpe0NkKHRoaXMsLTEpO3RoaXMuVj0hMTt0aGlzLnMmJnNkKHRoaXMucywhMSl9OwpoLlJhPWZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmlzRW5hYmxlZCgpJiZ0aGlzLmlzVmlzaWJsZSgpJiYoMCE9UmModGhpcyl8fHRoaXMuRGEpJiZEZCh0aGlzLGEpPyhhLmcoKSxhLmooKSwhMCk6ITF9Owp2YXIgRGQ9ZnVuY3Rpb24oYSxiKXt2YXIgYz1MKGEsYS5sKTtpZihjJiYiZnVuY3Rpb24iPT10eXBlb2YgYy5mYSYmYy5mYShiKXx8YS5zJiZhLnMhPWMmJiJmdW5jdGlvbiI9PXR5cGVvZiBhLnMuZmEmJmEucy5mYShiKSlyZXR1cm4hMDtpZihiLnNoaWZ0S2V5fHxiLmN0cmxLZXl8fGIubWV0YUtleXx8Yi5hbHRLZXkpcmV0dXJuITE7c3dpdGNoKGIuYyl7Y2FzZSAyNzp5ZChhKS5ibHVyKCk7YnJlYWs7Y2FzZSAzNjpFZChhKTticmVhaztjYXNlIDM1OkZkKGEpO2JyZWFrO2Nhc2UgMzg6aWYoInZlcnRpY2FsIj09YS5IKUdkKGEpO2Vsc2UgcmV0dXJuITE7YnJlYWs7Y2FzZSAzNzppZigiaG9yaXpvbnRhbCI9PWEuSClTYyhhKT9IZChhKTpHZChhKTtlbHNlIHJldHVybiExO2JyZWFrO2Nhc2UgNDA6aWYoInZlcnRpY2FsIj09YS5IKUhkKGEpO2Vsc2UgcmV0dXJuITE7YnJlYWs7Y2FzZSAzOTppZigiaG9yaXpvbnRhbCI9PWEuSClTYyhhKT9HZChhKTpIZChhKTtlbHNlIHJldHVybiExOwpicmVhaztkZWZhdWx0OnJldHVybiExfXJldHVybiEwfSx6ZD1mdW5jdGlvbihhLGIpe3ZhciBjPWIuZigpO2M9Yy5pZHx8KGMuaWQ9TGMoYikpO2EuSXx8KGEuST17fSk7YS5JW2NdPWJ9O1MucHJvdG90eXBlLnNhPWZ1bmN0aW9uKGEsYil7Q2EoYSxOLCJUaGUgY2hpbGQgb2YgYSBjb250YWluZXIgbXVzdCBiZSBhIGNvbnRyb2wiKTtTLmkuc2EuY2FsbCh0aGlzLGEsYil9O1MucHJvdG90eXBlLnRhPWZ1bmN0aW9uKGEsYixjKXtDYShhLE4pO2EuS3w9MjthLkt8PTY0O3RkKGEsMzIsITEpO2EubSYmMCE9YS55YSYmb2QoYSwhMSk7YS55YT0hMTt2YXIgZD1hLmI9PXRoaXM/VGModGhpcyxhKTotMTtTLmkudGEuY2FsbCh0aGlzLGEsYixjKTthLm0mJnRoaXMubSYmemQodGhpcyxhKTthPWQ7LTE9PWEmJihhPVJjKHRoaXMpKTthPT10aGlzLmw/dGhpcy5sPU1hdGgubWluKFJjKHRoaXMpLTEsYik6YT50aGlzLmwmJmI8PXRoaXMubD90aGlzLmwrKzphPHRoaXMubCYmYj50aGlzLmwmJnRoaXMubC0tfTsKdmFyIGFkPWZ1bmN0aW9uKGEsYil7aWYoYS5mKCkpdGhyb3cgRXJyb3IoIkNvbXBvbmVudCBhbHJlYWR5IHJlbmRlcmVkIik7YS5IPWJ9O1MucHJvdG90eXBlLmlzVmlzaWJsZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLlR9O3ZhciBBZD1mdW5jdGlvbihhLGIpe2EuVD1iO3ZhciBjPWEuZigpO2MmJihjLnN0eWxlLmRpc3BsYXk9Yj8iIjoibm9uZSIsWWMoeWQoYSksYS5PJiZhLlQpKX07Uy5wcm90b3R5cGUuaXNFbmFibGVkPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuT307Uy5wcm90b3R5cGUuWj1mdW5jdGlvbihhKXt0aGlzLk8hPWEmJnVjKHRoaXMsYT8iZW5hYmxlIjoiZGlzYWJsZSIpJiYoYT8odGhpcy5PPSEwLFFjKHRoaXMsZnVuY3Rpb24oYil7Yi5MYT9kZWxldGUgYi5MYTpiLlooITApfSkpOihRYyh0aGlzLGZ1bmN0aW9uKGIpe2IuaXNFbmFibGVkKCk/Yi5aKCExKTpiLkxhPSEwfSksdGhpcy5WPXRoaXMuTz0hMSksWWMoeWQodGhpcyksYSYmdGhpcy5UKSl9Owp2YXIgQ2Q9ZnVuY3Rpb24oYSxiKXsoYj1MKGEsYikpP1AoYiwhMCk6LTE8YS5sJiZQKEwoYSxhLmwpLCExKX0sRWQ9ZnVuY3Rpb24oYSl7SWQoYSxmdW5jdGlvbihiLGMpe3JldHVybihiKzEpJWN9LFJjKGEpLTEpfSxGZD1mdW5jdGlvbihhKXtJZChhLGZ1bmN0aW9uKGIsYyl7Yi0tO3JldHVybiAwPmI/Yy0xOmJ9LDApfSxIZD1mdW5jdGlvbihhKXtJZChhLGZ1bmN0aW9uKGIsYyl7cmV0dXJuKGIrMSklY30sYS5sKX0sR2Q9ZnVuY3Rpb24oYSl7SWQoYSxmdW5jdGlvbihiLGMpe2ItLTtyZXR1cm4gMD5iP2MtMTpifSxhLmwpfSxJZD1mdW5jdGlvbihhLGIsYyl7Yz0wPmM/VGMoYSxhLnMpOmM7dmFyIGQ9UmMoYSk7Yz1iLmNhbGwoYSxjLGQpO2Zvcih2YXIgZT0wO2U8PWQ7KXt2YXIgZj1MKGEsYyksZztpZihnPWYpZz1mLmlzVmlzaWJsZSgpJiZmLmlzRW5hYmxlZCgpJiYhIShmLnYmMik7aWYoZyl7YS5FYShjKTticmVha31lKys7Yz1iLmNhbGwoYSxjLGQpfX07ClMucHJvdG90eXBlLkVhPWZ1bmN0aW9uKGEpe0NkKHRoaXMsYSl9O3ZhciBUPWZ1bmN0aW9uKCl7fTtuKFQsTSk7ZGEoVCk7VC5wcm90b3R5cGUuYT1mdW5jdGlvbigpe3JldHVybiJnb29nLXRhYiJ9O1QucHJvdG90eXBlLmg9ZnVuY3Rpb24oKXtyZXR1cm4idGFiIn07VC5wcm90b3R5cGUuYz1mdW5jdGlvbihhKXt2YXIgYj1ULmkuYy5jYWxsKHRoaXMsYSk7KGE9YS5QYSkmJmImJihiLnRpdGxlPWF8fCIiKTtyZXR1cm4gYn07VC5wcm90b3R5cGUuZz1mdW5jdGlvbihhLGIpe2I9VC5pLmcuY2FsbCh0aGlzLGEsYik7dmFyIGM9Yi50aXRsZXx8IiI7YyYmKGEuUGE9Yyk7YS5vJjgmJihjPWEuYikmJmlhKGMuRykmJihRKGEsOCwhMSksYy5HKGEpKTtyZXR1cm4gYn07dmFyIEpkPWZ1bmN0aW9uKGEsYixjKXtOLmNhbGwodGhpcyxhLGJ8fFQuUigpLGMpO3RkKHRoaXMsOCwhMCk7dGhpcy5LfD05fTtuKEpkLE4pO1ZjKCJnb29nLXRhYiIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEpkKG51bGwpfSk7dmFyIFU9ZnVuY3Rpb24oKXt0aGlzLmg9InRhYmxpc3QifTtuKFUsWGMpO2RhKFUpO1UucHJvdG90eXBlLmI9ZnVuY3Rpb24oKXtyZXR1cm4iZ29vZy10YWItYmFyIn07VS5wcm90b3R5cGUuZz1mdW5jdGlvbihhLGIsYyl7dGhpcy5qfHwodGhpcy5hfHxLZCh0aGlzKSx0aGlzLmo9c2EodGhpcy5hKSk7dmFyIGQ9dGhpcy5qW2JdO2Q/KGFkKGEsTGQoZCkpLGEuQj1kKTpVLmkuZy5jYWxsKHRoaXMsYSxiLGMpfTtVLnByb3RvdHlwZS5jPWZ1bmN0aW9uKGEpe3ZhciBiPVUuaS5jLmNhbGwodGhpcyxhKTt0aGlzLmF8fEtkKHRoaXMpO2IucHVzaCh0aGlzLmFbYS5CXSk7cmV0dXJuIGJ9O3ZhciBLZD1mdW5jdGlvbihhKXt2YXIgYj1hLmIoKTthLmE9e3RvcDpiKyItdG9wIixib3R0b206YisiLWJvdHRvbSIsc3RhcnQ6YisiLXN0YXJ0IixlbmQ6YisiLWVuZCJ9fTt2YXIgVj1mdW5jdGlvbihhLGIsYyl7YT1hfHwidG9wIjthZCh0aGlzLExkKGEpKTt0aGlzLkI9YTtTLmNhbGwodGhpcyx0aGlzLkgsYnx8VS5SKCksYyk7TWQodGhpcyl9O24oVixTKTtoPVYucHJvdG90eXBlO2guQz1udWxsO2guRD1mdW5jdGlvbigpe1YuaS5ELmNhbGwodGhpcyk7TWQodGhpcyl9O2gudT1mdW5jdGlvbigpe1YuaS51LmNhbGwodGhpcyk7dGhpcy5DPW51bGx9O2guRWE9ZnVuY3Rpb24oYSl7Vi5pLkVhLmNhbGwodGhpcyxhKTt0aGlzLkcoTCh0aGlzLGEpKX07aC5HPWZ1bmN0aW9uKGEpe2E/cmQoYSwhMCk6dGhpcy5DJiZyZCh0aGlzLkMsITEpfTsKdmFyIE5kPWZ1bmN0aW9uKGEsYil7aWYoYiYmYj09YS5DKXtmb3IodmFyIGM9VGMoYSxiKSxkPWMtMTtiPUwoYSxkKTtkLS0pe3ZhciBlPWI7aWYoZS5pc1Zpc2libGUoKSYmZS5pc0VuYWJsZWQoKSl7YS5HKGIpO3JldHVybn19Zm9yKGMrPTE7Yj1MKGEsYyk7YysrKWlmKGQ9YixkLmlzVmlzaWJsZSgpJiZkLmlzRW5hYmxlZCgpKXthLkcoYik7cmV0dXJufWEuRyhudWxsKX19O2g9Vi5wcm90b3R5cGU7aC5hYj1mdW5jdGlvbihhKXt0aGlzLkMmJnRoaXMuQyE9YS50YXJnZXQmJnJkKHRoaXMuQywhMSk7dGhpcy5DPWEudGFyZ2V0fTtoLmJiPWZ1bmN0aW9uKGEpe2EudGFyZ2V0PT10aGlzLkMmJih0aGlzLkM9bnVsbCl9O2guWmE9ZnVuY3Rpb24oYSl7TmQodGhpcyxhLnRhcmdldCl9O2guJGE9ZnVuY3Rpb24oYSl7TmQodGhpcyxhLnRhcmdldCl9O2guSGE9ZnVuY3Rpb24oKXtMKHRoaXMsdGhpcy5sKXx8Q2QodGhpcyxUYyh0aGlzLHRoaXMuQ3x8TCh0aGlzLDApKSl9Owp2YXIgTWQ9ZnVuY3Rpb24oYSl7SChIKEgoSChPYyhhKSxhLCJzZWxlY3QiLGEuYWIpLGEsInVuc2VsZWN0IixhLmJiKSxhLCJkaXNhYmxlIixhLlphKSxhLCJoaWRlIixhLiRhKX0sTGQ9ZnVuY3Rpb24oYSl7cmV0dXJuInN0YXJ0Ij09YXx8ImVuZCI9PWE/InZlcnRpY2FsIjoiaG9yaXpvbnRhbCJ9O1ZjKCJnb29nLXRhYi1iYXIiLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBWfSk7ZnVuY3Rpb24gT2QoYSl7dmFyIGI9e3RvcDoiYm90dG9tIixib3R0b206InRvcCIsc3RhcnQ6InJpZ2h0IixlbmQ6ImxlZnQifVthLmxvY2F0aW9uXSxjPWEuZWxlbWVudElkLGQ9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic3R5bGUiKTtkLnRleHRDb250ZW50PSJcbiAgICBmaWVsZHNldCB7XG4gICAgICBwYWRkaW5nOiAxMHB4O1xuICAgICAgYm9yZGVyOiAxcHggc29saWQgIzM2OTtcbiAgICB9XG5cbiAgICAjIitjKyIgLmdvb2ctdGFiLWNvbnRlbnQge1xuICAgICAgbWluLWhlaWdodDogM2VtO1xuICAgICAgbWFyZ2luOiAwO1xuICAgICAgYm9yZGVyOiAiK2EuYm9yZGVyKyIgc29saWQgIithLmJvcmRlckNvbG9yKyI7XG4gICAgICBib3JkZXItdG9wOiAwO1xuICAgICAgaGVpZ2h0OiAiK2EuY29udGVudEhlaWdodCsiO1xuICAgICAgcGFkZGluZzogNHB4IDhweDtcbiAgICAgIG1hcmdpbi1yaWdodDogNHB4O1xuICAgICAgYmFja2dyb3VuZDogdmFyKC0tY29sYWItcHJpbWFyeS1zdXJmYWNlLWNvbG9yKTtcbiAgICAgIG92ZXJmbG93OiBhdXRvO1xuICAgIH1cblxuICAgICMiKwpjKyIgLmdvb2ctdGFiLWJhci0iK2EubG9jYXRpb24rIiAuZ29vZy10YWItc2VsZWN0ZWQge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tY29sYWItcHJpbWFyeS1zdXJmYWNlLWNvbG9yKTtcbiAgICAgIGJvcmRlcjogMXB4IHNvbGlkICIrYS5ib3JkZXJDb2xvcisiO1xuICAgICAgYm9yZGVyLSIrYisiOiAwcHg7XG4gICAgfVxuXG4gICAgIyIrYysiIC5nb29nLXRhYi1iYXItIithLmxvY2F0aW9uKyIge1xuICAgICAgcGFkZGluZy0iK2EubG9jYXRpb24rIjogNXB4ICFpbXBvcnRhbnQ7XG4gICAgICBib3JkZXItIitiKyI6IDFweCBzb2xpZCAiK2EuYm9yZGVyQ29sb3IrIiAhaW1wb3J0YW50O1xuICAgICAgYmFja2dyb3VuZDogdmFyKC0tY29sYWItcHJpbWFyeS1zdXJmYWNlLWNvbG9yKTtcbiAgICB9XG5cbiAgICAjIitjKyIgLmdvb2ctdGFiLWJhciB7XG4gICAgICAgbWFyZ2luOiAwO1xuICAgICAgIGJvcmRlcjogMDtcbiAgICAgICBwYWRkaW5nOiAwO1xuICAgICAgIGxpc3Qtc3R5bGU6IG5vbmU7XG4gICAgICAgY3Vyc29yOiBkZWZhdWx0O1xuICAgICAgIG91dGxpbmU6IG5vbmU7XG4gICAgICAgYmFja2dyb3VuZDogdmFyKC0tY29sYWItcHJpbWFyeS1zdXJmYWNlLWNvbG9yKTtcbiAgICAgICBtYXJnaW4tcmlnaHQ6IDRweDtcbiAgICAgIH1cblxuICAgICAjIisKYysiIC5nb29nLXRhYiB7XG4gICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgICAgIHBhZGRpbmc6IDRweCA4cHg7XG4gICAgICAgY29sb3I6IHZhcigtLWNvbGFiLXByaW1hcnktdGV4dC1jb2xvcik7XG4gICAgICAgdGV4dC1kZWNvcmF0aW9uOiBpbml0aWFsO1xuICAgICAgIGN1cnNvcjogZGVmYXVsdDtcbiAgICAgIH1cblxuICAgICAgIyIrYysiIC5nb29nLXRhYi1ob3ZlciB7XG4gICAgICAgIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWNvbGFiLWhpZ2hsaWdodGVkLXN1cmZhY2UtY29sb3IpO1xuICAgICAgfVxuICAgICAgIjtyZXR1cm4gZH0KdmFyIFBkPWZ1bmN0aW9uKGEpe3ZhciBiPWEuZWxlbWVudElkLGM9YS50YWJOYW1lcyxkPWEuc2VsZWN0ZWRJbmRleDsiY29udGVudEJvcmRlciJpbiBhfHwoYS5jb250ZW50Qm9yZGVyPSIwcHgiKTsiY29udGVudEhlaWdodCJpbiBhfHwoYS5jb250ZW50SGVpZ2h0PSJpbml0aWFsIik7ImJvcmRlckNvbG9yImluIGF8fChhLmJvcmRlckNvbG9yPSJ2YXIoLS1jb2xhYi1ib3JkZXItY29sb3IpIik7YS5sb2NhdGlvbnx8KGEubG9jYXRpb249InRvcCIpO3ZhciBlPWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIiMiK2IpLGY9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiZGl2Iik7Zi5jbGFzc0xpc3QuYWRkKCJnb29nLXRhYi1iYXIiKTt2YXIgZz1hLmxvY2F0aW9uO2YuY2xhc3NMaXN0LmFkZCgiZ29vZy10YWItYmFyLSIrZyk7Zm9yKHZhciBrPVtdLHA9YmEoYyksdz1wLm5leHQoKTshdy5kb25lO3c9cC5uZXh0KCkpe3c9dy52YWx1ZTt2YXIgQj1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJkaXYiKTsKQi5jbGFzc0xpc3QuYWRkKCJnb29nLXRhYiIpO0IudGV4dENvbnRlbnQ9dztmLmFwcGVuZENoaWxkKEIpO2sucHVzaChCKX0iYm90dG9tIiE9ZyYmZS5hcHBlbmRDaGlsZChmKTtwPW51bGw7aWYoInRvcCI9PWd8fCJib3R0b20iPT1nKXA9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiZGl2IikscC5jbGFzc0xpc3QuYWRkKCJnb29nLXRhYi1iYXItY2xlYXIiKTsidG9wIj09ZyYmcCYmZS5hcHBlbmRDaGlsZChwKTtCPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpO0IuY2xhc3NMaXN0LmFkZCgiZ29vZy10YWItY29udGVudCIpO3ZhciByYT1bXTtjPWJhKGMpO2Zvcih3PWMubmV4dCgpOyF3LmRvbmU7dz1jLm5leHQoKSl3PWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpLHcuaWQ9ZS5pZCsiX2NvbnRlbnRfIityYS5sZW5ndGgsdy5zdHlsZS5kaXNwbGF5PSJub25lIixCLmFwcGVuZENoaWxkKHcpLHJhLnB1c2godyk7ZS5hcHBlbmRDaGlsZChCKTsiYm90dG9tIj09ZyYmKHAmJgplLmFwcGVuZENoaWxkKHApLGUuYXBwZW5kQ2hpbGQoZikpO3ZhciBYPW5ldyBWKGcpO1BjKFgsZik7dmFyIFk9LTE7ZGMoWCwic2VsZWN0IixmdW5jdGlvbihaKXtaPWsuaW5kZXhPZihaLnRhcmdldC5mKCkpO1ohPVkmJigwPD1ZJiZZPHJhLmxlbmd0aCYmKHJhW1ldLnN0eWxlLmRpc3BsYXk9Im5vbmUiLFk9LTEpLDA8PVomJlo8cmEubGVuZ3RoJiYoWT1aLHJhW1ldLnN0eWxlLmRpc3BsYXk9ImlubGluZSIsd2luZG93LmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCJyZXNpemUiKSksZ29vZ2xlLmNvbGFiLm91dHB1dC5yZXNpemVJZnJhbWVUb0NvbnRlbnQoKSksWC5HKEwoWCxZKSkpfSk7WC5HKEwoWCxkKSk7d2luZG93W2JdPXtzZXRTZWxlY3RlZFRhYkluZGV4OmZ1bmN0aW9uKFope1guRyhMKFgsWikpfX07ZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChPZChhKSl9LFFkPVsiY29sYWJfbGliIiwiY3JlYXRlVGFiQmFyIl0sVz1sOwpRZFswXWluIFd8fCJ1bmRlZmluZWQiPT10eXBlb2YgVy5leGVjU2NyaXB0fHxXLmV4ZWNTY3JpcHQoInZhciAiK1FkWzBdKTtmb3IodmFyIFJkO1FkLmxlbmd0aCYmKFJkPVFkLnNoaWZ0KCkpOylRZC5sZW5ndGh8fHZvaWQgMD09PVBkP1dbUmRdJiZXW1JkXSE9PU9iamVjdC5wcm90b3R5cGVbUmRdP1c9V1tSZF06Vz1XW1JkXT17fTpXW1JkXT1QZDt9KS5jYWxsKHRoaXMpOwovLyBjbGFuZy1mb3JtYXQgb24K",
              "ok": true,
              "headers": [
                [
                  "content-type",
                  "application/javascript"
                ]
              ],
              "status": 200,
              "status_text": ""
            }
          },
          "base_uri": "https://localhost:8080/",
          "height": 239
        },
        "outputId": "f92b38d3-5758-402b-8ea8-2418de6c1001"
      },
      "source": [
        "%%logica AvengerMortality\n",
        "@Engine(\"psql\");\n",
        "\n",
        "Probability(x) = Sum(if x == \"yes\" then 1.0 else 0.0) / Sum(1.0);\n",
        "\n",
        "AvengerMortality(gender:, death_probability? Probability= death) distinct :-\n",
        "  avengers(gender: avenger_gender, death1: death),\n",
        "  (gender == avenger_gender | gender == \"all\");"
      ],
      "execution_count": 3,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<link rel=stylesheet type=text/css href='/nbextensions/google.colab/tabbar.css'></link>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": [
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<script src='/nbextensions/google.colab/tabbar_main.min.js'></script>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": [
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<div id=\"id1\"></div>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": [
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f47e192c-c300-11eb-9554-0242ac1c0002\"] = colab_lib.createTabBar({\"location\": \"top\", \"elementId\": \"id1\", \"tabNames\": [\"AvengerMortality\", \"(Log)\"], \"initialSelection\": 0, \"contentBorder\": [\"0px\"], \"contentHeight\": [\"initial\"], \"borderColor\": [\"#a7a7a7\"]});\n",
              "//# sourceURL=js_45f241dd56"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f47e8ce0-c300-11eb-9554-0242ac1c0002\"] = window[\"id1\"].setSelectedTabIndex(0);\n",
              "//# sourceURL=js_5679782d0e"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f480c76c-c300-11eb-9554-0242ac1c0002\"] = google.colab.output.getActiveOutputArea();\n",
              "//# sourceURL=js_61ffc9e11c"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_1",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f4812d06-c300-11eb-9554-0242ac1c0002\"] = document.querySelector(\"#id1_content_1\");\n",
              "//# sourceURL=js_7c2b3b7c51"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_1",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f4819502-c300-11eb-9554-0242ac1c0002\"] = google.colab.output.setActiveOutputArea(window[\"f4812d06-c300-11eb-9554-0242ac1c0002\"]);\n",
              "//# sourceURL=js_fa8b70e816"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_1",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f481fbe6-c300-11eb-9554-0242ac1c0002\"] = window[\"id1\"].setSelectedTabIndex(1);\n",
              "//# sourceURL=js_6db4b09869"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_1",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "stream",
          "text": [
            "Running AvengerMortality\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f485d3b0-c300-11eb-9554-0242ac1c0002\"] = google.colab.output.setActiveOutputArea(window[\"f480c76c-c300-11eb-9554-0242ac1c0002\"]);\n",
              "//# sourceURL=js_42b1f12b15"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_1",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f4885cac-c300-11eb-9554-0242ac1c0002\"] = google.colab.output.getActiveOutputArea();\n",
              "//# sourceURL=js_89b338a39a"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f488b13e-c300-11eb-9554-0242ac1c0002\"] = document.querySelector(\"#id1_content_0\");\n",
              "//# sourceURL=js_6ac6276759"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f48958e6-c300-11eb-9554-0242ac1c0002\"] = google.colab.output.setActiveOutputArea(window[\"f488b13e-c300-11eb-9554-0242ac1c0002\"]);\n",
              "//# sourceURL=js_30b5c5d26e"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f489ae7c-c300-11eb-9554-0242ac1c0002\"] = window[\"id1\"].setSelectedTabIndex(0);\n",
              "//# sourceURL=js_76552cfc1a"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<link rel=stylesheet type=text/css href='/nbextensions/google.colab/tabbar.css'></link>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "outputarea_id1",
              "outputarea_id2",
              "user_output"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<script src='/nbextensions/google.colab/tabbar_main.min.js'></script>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "outputarea_id1",
              "outputarea_id2",
              "user_output"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<div id=\"id2\"></div>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "outputarea_id1",
              "outputarea_id2",
              "user_output"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f48b8a4e-c300-11eb-9554-0242ac1c0002\"] = colab_lib.createTabBar({\"location\": \"top\", \"elementId\": \"id2\", \"tabNames\": [\"SQL\", \"Result\"], \"initialSelection\": 0, \"contentBorder\": [\"0px\"], \"contentHeight\": [\"initial\"], \"borderColor\": [\"#a7a7a7\"]});\n",
              "//# sourceURL=js_ea688a18f2"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "outputarea_id1",
              "outputarea_id2",
              "user_output"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f48befe8-c300-11eb-9554-0242ac1c0002\"] = window[\"id2\"].setSelectedTabIndex(0);\n",
              "//# sourceURL=js_bd78c71639"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "outputarea_id1",
              "outputarea_id2",
              "user_output"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f49112d4-c300-11eb-9554-0242ac1c0002\"] = google.colab.output.getActiveOutputArea();\n",
              "//# sourceURL=js_0628fe4068"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "id2_content_0",
              "outputarea_id1",
              "outputarea_id2",
              "user_output"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f491aa32-c300-11eb-9554-0242ac1c0002\"] = document.querySelector(\"#id2_content_0\");\n",
              "//# sourceURL=js_de9af370e5"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "id2_content_0",
              "outputarea_id1",
              "outputarea_id2",
              "user_output"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f4953b84-c300-11eb-9554-0242ac1c0002\"] = google.colab.output.setActiveOutputArea(window[\"f491aa32-c300-11eb-9554-0242ac1c0002\"]);\n",
              "//# sourceURL=js_613391cb48"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "id2_content_0",
              "outputarea_id1",
              "outputarea_id2",
              "user_output"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f495f1be-c300-11eb-9554-0242ac1c0002\"] = window[\"id2\"].setSelectedTabIndex(0);\n",
              "//# sourceURL=js_38704b08d6"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "id2_content_0",
              "outputarea_id1",
              "outputarea_id2",
              "user_output"
            ]
          }
        },
        {
          "output_type": "stream",
          "text": [
            "The following query is stored at \u001b[1mAvengerMortality_sql\u001b[0m variable.\n",
            "-- Initializing PostgreSQL environment.\n",
            "set client_min_messages to warning;\n",
            "create schema if not exists logica_test;\n",
            "\n",
            "WITH t_0_AvengerMortality_MultBodyAggAux AS (SELECT * FROM (\n",
            "  \n",
            "    SELECT\n",
            "      avengers.gender AS gender,\n",
            "      avengers.death1 AS death_probability\n",
            "    FROM\n",
            "      avengers\n",
            "   UNION ALL\n",
            "  \n",
            "    SELECT\n",
            "      'all' AS gender,\n",
            "      t_1_avengers.death1 AS death_probability\n",
            "    FROM\n",
            "      avengers AS t_1_avengers\n",
            "  \n",
            ") AS UNUSED_TABLE_NAME  )\n",
            "SELECT\n",
            "  AvengerMortality_MultBodyAggAux.gender AS gender,\n",
            "  ((SUM(CASE WHEN (AvengerMortality_MultBodyAggAux.death_probability = 'yes') THEN 1.0 ELSE 0.0 END)) / (SUM(1.0))) AS death_probability\n",
            "FROM\n",
            "  t_0_AvengerMortality_MultBodyAggAux AS AvengerMortality_MultBodyAggAux\n",
            "GROUP BY gender;\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f498c31c-c300-11eb-9554-0242ac1c0002\"] = google.colab.output.setActiveOutputArea(window[\"f49112d4-c300-11eb-9554-0242ac1c0002\"]);\n",
              "//# sourceURL=js_22e038e25a"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "id2_content_0",
              "outputarea_id1",
              "outputarea_id2",
              "user_output"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f49c0c84-c300-11eb-9554-0242ac1c0002\"] = google.colab.output.setActiveOutputArea(window[\"f4885cac-c300-11eb-9554-0242ac1c0002\"]);\n",
              "//# sourceURL=js_37043cfb95"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f49e81c6-c300-11eb-9554-0242ac1c0002\"] = google.colab.output.getActiveOutputArea();\n",
              "//# sourceURL=js_befc477143"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_1",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f49ed7b6-c300-11eb-9554-0242ac1c0002\"] = document.querySelector(\"#id1_content_1\");\n",
              "//# sourceURL=js_330af9c55b"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_1",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f49f3206-c300-11eb-9554-0242ac1c0002\"] = google.colab.output.setActiveOutputArea(window[\"f49ed7b6-c300-11eb-9554-0242ac1c0002\"]);\n",
              "//# sourceURL=js_906ca1cde7"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_1",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f49f8fb2-c300-11eb-9554-0242ac1c0002\"] = window[\"id1\"].setSelectedTabIndex(1);\n",
              "//# sourceURL=js_5b7fe91c35"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_1",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f4a2671e-c300-11eb-9554-0242ac1c0002\"] = google.colab.output.setActiveOutputArea(window[\"f49e81c6-c300-11eb-9554-0242ac1c0002\"]);\n",
              "//# sourceURL=js_9ba35d25c4"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_1",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f4a4af10-c300-11eb-9554-0242ac1c0002\"] = google.colab.output.getActiveOutputArea();\n",
              "//# sourceURL=js_6529151856"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f4a59560-c300-11eb-9554-0242ac1c0002\"] = document.querySelector(\"#id1_content_0\");\n",
              "//# sourceURL=js_8156432103"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f4a5f500-c300-11eb-9554-0242ac1c0002\"] = google.colab.output.setActiveOutputArea(window[\"f4a59560-c300-11eb-9554-0242ac1c0002\"]);\n",
              "//# sourceURL=js_8da8504cd2"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f4a65720-c300-11eb-9554-0242ac1c0002\"] = window[\"id1\"].setSelectedTabIndex(0);\n",
              "//# sourceURL=js_88cc3d8f20"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "outputarea_id1"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f4a83c5c-c300-11eb-9554-0242ac1c0002\"] = google.colab.output.getActiveOutputArea();\n",
              "//# sourceURL=js_6a4186126f"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "id2_content_1",
              "outputarea_id1",
              "outputarea_id2",
              "user_output"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f4a89abc-c300-11eb-9554-0242ac1c0002\"] = document.querySelector(\"#id2_content_1\");\n",
              "//# sourceURL=js_81e3c2df2d"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "id2_content_1",
              "outputarea_id1",
              "outputarea_id2",
              "user_output"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f4a8fa5c-c300-11eb-9554-0242ac1c0002\"] = google.colab.output.setActiveOutputArea(window[\"f4a89abc-c300-11eb-9554-0242ac1c0002\"]);\n",
              "//# sourceURL=js_24bfaaccd8"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "id2_content_1",
              "outputarea_id1",
              "outputarea_id2",
              "user_output"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f4a961d6-c300-11eb-9554-0242ac1c0002\"] = window[\"id2\"].setSelectedTabIndex(1);\n",
              "//# sourceURL=js_4f6c0e485d"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "id2_content_1",
              "outputarea_id1",
              "outputarea_id2",
              "user_output"
            ]
          }
        },
        {
          "output_type": "stream",
          "text": [
            "The following table is stored at \u001b[1mAvengerMortality\u001b[0m variable.\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>gender</th>\n",
              "      <th>death_probability</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>female</td>\n",
              "      <td>0.362069</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>male</td>\n",
              "      <td>0.417391</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>all</td>\n",
              "      <td>0.398844</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "   gender  death_probability\n",
              "0  female           0.362069\n",
              "1    male           0.417391\n",
              "2     all           0.398844"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "id2_content_1",
              "outputarea_id1",
              "outputarea_id2",
              "user_output"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f4b31a96-c300-11eb-9554-0242ac1c0002\"] = google.colab.output.setActiveOutputArea(window[\"f4a83c5c-c300-11eb-9554-0242ac1c0002\"]);\n",
              "//# sourceURL=js_1e5913d4ec"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "id2_content_1",
              "outputarea_id1",
              "outputarea_id2",
              "user_output"
            ]
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "application/javascript": [
              "window[\"f4b514cc-c300-11eb-9554-0242ac1c0002\"] = google.colab.output.setActiveOutputArea(window[\"f4a4af10-c300-11eb-9554-0242ac1c0002\"]);\n",
              "//# sourceURL=js_d5a5b5f3aa"
            ],
            "text/plain": [
              "<IPython.core.display.Javascript object>"
            ]
          },
          "metadata": {
            "tags": [
              "id1_content_0",
              "outputarea_id1"
            ]
          }
        }
      ]
    }
  ]
}